一 单点登录的方式
1.1 sso的三种方式
1.2 jwttoken
1.2.1 说明
1.token的3部分: 1.头部信息;2.有效载体;3.hash签名
2.客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。
此后,客户端将在与服务器交互中都会带JWT。如果将它存储在Cookie中,就可以自动发送,并且不会跨域,因此一般是将它放入HTTP请求的Header Authorization字段中。当跨域时,也可以将JWT被放置于POST请求的数据主体中。
3.作用:
- JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。
- 生产的token可以包含基本信息,比如id、用户昵称、头像等信息,避免再次查库
- 存储在客户端,不占用服务端的内存资源
1.2.2 工具类
1.pom的配置
<!-- JWT-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
2.工具类
package com.atguigu.commonutils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
/**
* @author helen
* @since 2019/10/16
*/
public class JwtUtils {
//常量
public static final long EXPIRE = 1000 * 60 * 60 * 24; //token过期时间
public static final String APP_SECRET = "ukc8BDbRigUDaY6pZFfWus2jZWLPHO"; //秘钥
//生成token字符串的方法
public 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.currentTimeMillis() + EXPIRE))
.claim("id", id) //设置token主体部分 ,存储用户信息
.claim("nickname", nickname)
.signWith(SignatureAlgorithm.HS256, APP_SECRET)
.compact();
return JwtToken;
}
/**
* 判断token是否存在与有效
* @param jwtToken
* @return
*/
public static boolean checkToken(String jwtToken) {
if(StringUtils.isEmpty(jwtToken)) return false;
try {
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 判断token是否存在与有效
* @param request
* @return
*/
public static boolean checkToken(HttpServletRequest request) {
try {
String jwtToken = request.getHeader("token");
if(StringUtils.isEmpty(jwtToken)) return false;
Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 根据token字符串获取会员id
* @param request
* @return
*/
public static String getMemberIdByJwtToken(HttpServletRequest request) {
String jwtToken = request.getHeader("token");
if(StringUtils.isEmpty(jwtToken)) return "";
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
Claims claims = claimsJws.getBody();
return (String)claims.get("id");
}
}
1.3 阿里云短信发送功能
1.3.1 阿里云的短信服务注册配置
1.3.2 短信发送的案例
1.流程: 【手机号+code】 作为参数,调用阿里云的短息服务接口,阿里云短息服务平台将code发送到提交的那个手机号上。
2.代码
2.1)使用 redis作为验证码的超时判断。
2.2)service层代码
二 注册功能 设计的核心流程
2.1 流程图
2.2 注册代码
1.从redis取出code和输入的code进行判断
2.密码使用md5加密存储
public void register(RegisterVo registerVo) {
//获取注册的数据
String code = registerVo.getCode(); //验证码
String mobile = registerVo.getMobile(); //手机号
String nickname = registerVo.getNickname(); //昵称
String password = registerVo.getPassword(); //密码
//非空判断
if(StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)
|| StringUtils.isEmpty(code) || StringUtils.isEmpty(nickname)) {
throw new GuliException(20001,"注册失败");
}
//判断验证码
//获取redis验证码
String redisCode = redisTemplate.opsForValue().get(mobile);
if(!code.equals(redisCode)) {
throw new GuliException(20001,"注册失败");
}
//判断手机号是否重复,表里面存在相同手机号不进行添加
QueryWrapper<UcenterMember> wrapper = new QueryWrapper<>();
wrapper.eq("mobile",mobile);
Integer count = baseMapper.selectCount(wrapper);
if(count > 0) {
throw new GuliException(20001,"注册失败");
}
//数据添加数据库中
UcenterMember member = new UcenterMember();
member.setMobile(mobile);
member.setNickname(nickname);
member.setPassword(MD5.encrypt(password));//密码需要加密的
member.setIsDisabled(false);//用户不禁用
member.setAvatar("http://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoj0hHXhgJNOTSOFsS4uZs8x1ConecaVOB8eIl115xmJZcT4oCicvia7wMEufibKtTLqiaJeanU2Lpg3w/132");
baseMapper.insert(member);
}
前端页面定时器的获取
2.3 登录代码截图
1.登录成功后,将信息入到数据库中。
2.4 登录后获取用户信息显示
2.4.1 流程图