开发者学堂课程【微服务+全栈在线教育实战项目演练(SpringCloud Alibaba+SpringBoot):登录功能(接口)】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/667/detail/11446
登录功能(接口)
内容介绍:
一.在 service 下面创建子模块 service-ucenter
二.创建用户表,使用代码生成器生成代码
一.在 service 下面创建子模块 service-ucenter
创建之后可能会遇到的问题:创建的图标不会变。
解决办法:点右键,找到 Open Module Settings 修改即可。
注:要等待下面加载完成之后才能进行修改。
二.创建用户表,使用代码生成器生成代码
1.创建 ucenter_member 表
首先看数据库表,点击数据库脚本,有个叫 guli_ucenter.sql 的脚本,打开之后有张表,叫 ucenter_member,意思是用户中心会员表。
下面根据语句创建这个表。
在其他模块中把代码生成器复制到ucenter的test里。复制之后,里面需要改几个地方:
- 路径改成 service_ucenter
- 包配置改成自己的名字,这里的名字是 educenter
- 策略配置里加上表的名字。因为我们的表叫 ucenter_member,把表的名称复制过来。
改完之后把代码执行,生出相关代码,之后再往下生成接口。
执行之后就会根据我们的表生成 controller,service,mapper,实体类。
resources 里有一个相关的配置文件,把配置文件从课件中直接复制过去:
#服务端口
server.port=8006
#服务名
spring. application. name=service
-
msm
#mysql数据库连接
spring. datasource. driver -class
-
name=com
.
mysql.cj.jdbc. Driver
spring.datasource.url=jdbc:mysql://localhost:3306/guli?serverTimezone
=
GMT%2B8
spring. datasource.username=root
spring. datasource.
p
assword
=
root
spring.
redis.
host=192.168.44.132
spring.redis.port=6379
spring.redis.database= 0
spring. redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis. lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring. redis. lettuce.pool.max-idle=5
spring.redis. lettuce.pool.min-idle=0
#最小空闲
#返回json的全局时间格式
spring. jackson.
d
ate
-
format=yyyy-MM-dd HH:mm:ss
spring.jackson. time-zone=GMT+8
#配置mapper xml文件的路径
Mybatis
-
plus.mapper-locations=classpath:com/atguigu/
educenter
/mapper/xml/*.xml
#mybatis日志
Mybatis
-
plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
service_msm 发送短信的事好用的端口号是8005,所以 ucenter 的端口号就需要改成8006。
Redis 改成自己的地址。
配置 mapper xml 文件的路径改成educenter。
配置文件写完后还有个启动类,之前已经写过了。
@
ComponentScan({"co
m
. Atguigu
“}
)
@SpringBootApplication
@
MapperScan("co
m
. atguigu
.
educenter.mapper")
需要加上@ComponentScan和@SpringBootApplication。这个过程中要用到mapper,所以得加一个 mapper 扫描。Mapper 扫描需要些配置类或者写到启动类上都可以。
然后加上 mapper 包的地址 com. atguigu .educenter.mapper。
这样就把项目的准备工作完成了。生成了代码,创建了启动类,写出了配置文件。
创建 controller 编写登录和注册方法
先写注册接口,再写登录接口。
在 service_ucenter 中找到 controller,点击,开始写:
@RestController
@RequestMapping("/educenter/member")
@
CrossOrigin
public class UcenterMemberController{
@Autowired
private UcenterMemberService memberService
;
//登录
@GetMapping("login”)
public R loginUser(@RequestBody UcenterMember member){
//调用 service方法实现登录
//返回 token 值,使用 jwt 生成
S
tring
token
=memberService. login(member)
;
Return
R.
ok()
.data(“token”,token);
}
//注册
做登录的话,最原始的方式登录,需要有用户名和密码,根据用户名和密码到数据库中查,然后做判断是否相同,然后实现登录。
通过对象传递用户名和密码。写 requestbody,直接在实体类中直接传入用户名和数据。
调用service方法实现登录也就是Service里面显示登录最终过程。过程中有这样一个特点。上午有一张图显示的是单点登录的三种方式,第三种方式中是使用token实现,在登录之后要返回token的一个字符串,然后把字符串通过地址栏进行传递。所以现在把这个方法让他在登录成功之后返回一个值,也就是返回token值。
总结:
这个过程就是通过对象得到用户信息,调 service 中的方法做一个查询判断登录是否正确。
如果正确在方法中就把token值返回,因为做单点登录是需要token这个值的,而token 的值需要通过上节课写的jwt生成。
在 service 里创建登录的方法,创建之后,点击实现类,在实现类中写下登录方法,那登录应该怎么来写?
最原始的是根据用户名密码做个查询就可以了。
用UserMember完全可以,但是我们接下来写的就更细致一点。
因为登录过程中有用户名,有密码,包括在表里面还有一个字段叫手机号,和密码也可以登录。
还有一个字段叫 is_disabled,表示的是用户是否被禁用。
它的默认值是0,就是不禁用。
所以多做几个判断,判断手机号对不对,判断密码对不对,再判断手机号是否被禁用,下面就具体来做一下。
//登录的方法
@Override
public String login(UcenterMember member){
//获取登录手机号和密码
String mobile = member.getMobile
();
String password = member.getPassword();
//手机号和密码非空判断
if(StringUtils.isEmpty(mobile) ll StringUtils.isEmpty(password)){
throw new GuliException(20001,"登录失败”);
}
//判断手机号是否正确
QueryWrapper<UcenterMember>
wrapper
=
new QueryWrapper<>()
;
wrapper.eq(column:"mobile",mobile);
UcenterMember
mobileMember=baseMapper.selectOne(wrapper)
//判断查询对象是否为空
if(mobileMember==null){//没有这个手机号
throw new GuliException(20001,"登录失败”)
;
//判断密码
//因为存储到数据库中的密码肯定加密的
//把输入的密码进行加密,再跟数据库中的密码比较
//加密方式
MD
5
if(!MD
5
.encrypt(password).equals(mobileMember.getPassword())) {
throw new GuliException(20001,“登录失败”):
}
//判断用户是否禁用
if(mobileMember.getIsDisabled()){
throw new GuliException(20001,“登录失败
”
)
;
//登录成功
/
/
生成token字符串,使用jwt工具类
String
jwtToken=JwtUtils.getJwtToken(mobileMember.getId(),mobileMember.getNickname());
return jwtToken;
如果 UcenterMember member 这两个值本身都为空或者某一个为空,就不需要往下写了。所以要做手机号和密码的非空判断。
都判断完成之后就成功了,之后回到 controller。登录成功之后要返回token值,token 值生成要用到 jwt 工具类,而 jwt 在 common_utils 里的 JwtUtils。
这样,登录的接口就完成了。
注:
生成 token 字符串的方法
blic static String getJwtToken(String id, String nickname){
String JwtToken = Jwts.builder()
.setHeaderParam
(
"typ", "JWT
“
)
.setHeaderParam
(
"alg", "HS256”)
.setSubject("guli-user")
.
setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMlillis()+ EXPIRE))
.claim("id”,id) //设置token主体部分,存储用户信息
.claim "nickname", nickname)
.signWith(SignatureAlgorithm.HS256, APP_SECRED)
.compact():
return JwtToken.
完成之后,如果测试,会出现一个问题。在这里已经直接避免掉了。
是关于密码的问题。我们看数据库表里的密码这个数据很繁琐,没有办法记住去输入。
这个密码不是我们常规的密码,而是做了加密之后存储到数据库中。
数据库中不存储明文密码。在输入的时候,不可能去输入数据库显示的密码。
所以判断密码那一行肯定会错误异常,因为输入的密码没有加密,数据库中的密码肯定是加密了的。所以自己写的密码肯定要加密之后再跟数据库作比较。
加密方式:MD5。这种加密方式的特点是只能加密不能解密。在今天的源码里提供了工具类 MD5.java,可以直接用。把 MD5复制到 common 里即可。
写代码的时候,随着代码经验的积累,很多 bug 可以慢慢避免。