JWT 单点登录,小甲鱼数据结构百度云
用户登录,发送账号密码
服务的认证,通过后根据 secret 生成 token
将生成的 token 返回给浏览器
用户每次请求携带 token
服务端利用公钥解读 jwt 签名,判断签名有效后,从 Payload 中获取用户信息
处理请求,返回响应结果
=======================================================================
1)创建登录鉴权服务,引入依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
</dependency>
2)配置文件的工具类
/**
读取配置文件的配置类
*/
@Data
@Configuration
//读取配置文件的注解
@ConfigurationProperties(prefix = "blb.jwt")
public class JwtProperties {
private String secret;//秘钥
private String pubKeyPath;//公钥路径
private String priKeyPath;//私钥路径
private String cookieName;//cookie 名称
private Integer expire;//cookie 过期时间
private Integer cookieMaxAge;//cookie 生命周期
private PublicKey publicKey;//公钥
private PrivateKey privateKey;//私钥
//在构造方法之后自动执行
@PostConstruct
public void init(){
File pubKey = new File(pubKeyPath);
File priKey = new File(priKeyPath);
try {
//判断公钥和私钥如果不存在就创建
if (!priKey.exists() || !pubKey.exists()) {
//创建公钥和私钥文件
RsaUtils.generateKey(this.pubKeyPath, this.priKeyPath, this.secret);
}
//读取公钥和私钥内容
this.publicKey = RsaUtils.getPublicKey(this.pubKeyPath);
this.privateKey = RsaUtils.getPrivateKey(this.priKeyPath);
}catch (Exception ex){
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
}
application.properties
#秘钥
blb.jwt.secret=chenheng0611@#$%
#公钥路径
blb.jwt.pubKeyPath=D:\java_code\pub.rsa
#私钥路径
blb.jwt.priKeyPath=D:\java_code\pri.rsa
#cookie 名称
blb.jwt.cookieName=token
#cookie 过期时间
blb.jwt.expire=30
#cookie 生命周期
blb.jwt.cookieMaxAge=1800
UserService
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserInfo> implements IUserService {
@Override
public UserInfo login(String username, String password) {
//查询用户
UserInfo user = this.getOne(new QueryWrapper<UserInfo>().lambda().eq(UserInfo::getUsername, username));
if(user == null){
return null;
}
//将密码加密加盐后进行匹配
String encrypt = Md5Utils.encrypt(password, user.getSalt());
if(encrypt.equals(user.getPassword())){
return user;
}
return null;
}
}
UserController
/**
登录验证控制器
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
@Autowired
private JwtProperties properties;
@PostMapping("/login")
public JsonResult<UserInfo> login(HttpServletRequest request, HttpServletResponse response) throws Exception {
String username = request.getParameter("username");
String password = request.getParameter("password");
UserInfo info = userService.login(username, password);
if(info != null){
//验证通过,将用户加密为 token
String token = JwtUtils.generateToken(info, properties.getPrivateKey(), properties.getExpire());
//保存 token 到 cookie 中
CookieUtils.setCookie(request,response,properties.getCookieName(),token,
properties.getCookieMaxAge(),null,true);
return new JsonResult<>(1,info);
}
return new JsonResult<>(0,null);
}
}
登录页面
<template>
<el-card style="width: 480px">
<span style="color:red">{{msg}}</span>
<el-form v-model="form">
<el-input v-model="form.username" placeholder="请输入账号"></el-input>
<el-input type="password" v-model="form.password" placeholder="请输入密码"></el-input>
<el-button @click="login">登录</el-button>
</el-form>
</el-card>
</template>
<script>
export default {
name: "Login",
data(){
return{
msg:"",
form:{username:"",password:""}
}
},
methods:{
login(){
this.qs.stringify(this.form))
.then(res => {
if(res.data.code == 1){
this.$message.info("登录成功");
this.$router.push("/index");
}else{
this.msg = "账号或密码错误";
}
});
}
}
}
</script>
解决 cookie 写入失败的问题
原因 1:出现跨域,导致 Cookie 不能写入
1)CORS 的配置
2)axios 的配置
原因 2:Nginx 转发域名不一致的问题
Nginx 转发配置 : proxy_set_header Host $host;
原因 3:zuul 的敏感头过滤
关闭敏感头过滤
解决 Cookie 写入问题后,将公钥复制到网关服务器上,在网关中进行 token 解析实现统一的访问鉴权
网关判断用户登录状态
1)配置白名单,直接通过不进行登录验证
2)创建过滤器 ZuulFilter
3)过滤到白名单就直接放行
4)非白名单的请求,获得 cookie 中的 token,解析 token
5)如果解析成功,放行,解析失败,就进行拦截
网关的配置文件工具类
@Data
@Configuration
//读取配置文件的注解
@ConfigurationProperties(prefix = "blb.jwt")
public class JwtProperties {
private
List<String> whiteList;//白名单
private String pubKeyPath;//公钥路径
private String cookieName;//cookie 名称
private PublicKey publicKey;//公钥
//在构造方法之后自动执行
@PostConstruct
public void init(){
try {
//读取公钥内容
this.publicKey = RsaUtils.getPublicKey(this.pubKeyPath);
}catch (Exception ex){
ex.printStackTrace();
throw new RuntimeException(ex);
}
}
}
application.properties
白名单
blb.jwt.whiteList=/api/auth-api
公钥路径
blb.jwt.pubKeyPath=D:\java_code\pub.rsa
cookie 名称
blb.jwt.cookieName=token
鉴权过滤器
/**
登录鉴权的过滤器
*/
@Component
public class AuthFilter extends ZuulFilter {
@Autowired
private JwtProperties properties;
@Override
评论