springboot使用jwt进行权限验证
springboot使用jwt进行权限验证
依赖准备
首先导入对应的依赖
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
</dependencies>
这里需要用到一些工具类来方便我们进行操作

工具类中默认的数据封装对应的user只有两个属性,即用户名、密码,一般也不需要进行修改。
属性配置
对于信息的加密解密,我们需要有公钥和私钥,在application.yml中我们需要定义配置信息。
tens:
jwt:
secret: leyou@Login(Auth}*^31)&heiMa%
pubKeyPath: G:\\tensquare\\rsa\\rsa.pub
priKeyPath: G:\\tensquare\\rsa\\rsa.pri
expire: 30
cookieName: TQ_TOKEN
cookieMaxAge: 30
注意格式,以及目录不要使用中文路径,还有在IDEA的编码属性没设置好的话不要使用中文注解,不然都会报错!
接下来自然是在属性类中加载这些数据了
@ConfigurationProperties(prefix = "tens.jwt")
public class JwtProperties {
private String secret;
private String pubkeyPath;
private String prikeyPath;
private int expire;
private PublicKey publicKey;
private PrivateKey privateKey;
private String cookieName;
private Integer cookieMaxAge;
private static final Logger logger = LoggerFactory.getLogger(JwtProperties.class);
/**
* @PostContruct: 在构造方法执行后执行该方法
*/
@PostConstruct
public void init(){
try{
File pubkey = new File(pubkeyPath);
File prikey = new File(prikeyPath);
if(!pubkey.exists() || !prikey.exists()){
//如果没有密钥文件的话,就生成公钥和私钥
RsaUtils.generateKey(pubkeyPath,prikeyPath,secret);
}
//获取公钥私钥
this.publicKey = RsaUtils.getPublicKey(pubkeyPath);
this.privateKey = RsaUtils.getPrivateKey(prikeyPath);
}catch (Exception e){
logger.error("初始化公钥私钥失败!",e);
throw new RuntimeException();
}
}
}
这里省略了getter、setter,记得要写,不然数据加载会出错。还有配置文件的前缀要写对。这里并没有使用@Compenent这种方式将配置类加载到spring容器里去。而是选择了在需要使用配置类的地方加上@EnableConfigurationProperties({JwtProperties.class})注解。
登录验证
接下来我们就可以将登陆方法修改成先进行数据库验证,如果验证成功就利用jwt来生成对应的token以及公钥密钥,再将token放入cookie,这样用户进行其他操作的时候我们就可以进行状态以及权限判断了。
AuthController下的登录验证方法
@PostMapping("accredit")
public Result authentication(@RequestParam("username")String username,
@RequestParam("password")String password,
HttpServletRequest request, HttpServletResponse response){
//首先进行登录验证,即先判断账号密码是否正确,不正确的话直接返回失败信息,正确的话就把token写入cookie
String token = this.authService.authentication(username,password);
System.out.println(prop);
if(StringUtils.isBlank(token)){//即用户名或者密码错误,没有成功获取token
return new Result(false, StatusCode.ERROR,"登录失败");
}
//将token写入cookie,并指定HttpOnly为true,防止前端通过js进行修改
CookieUtils.setCookie(request,response,prop.getCookieName(),token,prop.getCookieMaxAge(),null,true);
return new Result(true,StatusCode.OK,"登录验证成功");
}
接下来就该写验证的service了。
AuthService
@Service
public class AuthService {
@Autowired
private UserDao userDao;
@Autowired
private JwtProperties properties;
public String authentication(String username, String password) {
try{
UserInfo userInfo = new UserInfo();
userInfo.setUsername(username);
userInfo.setPassword(password);
UserInfo user = this.userDao.selectOne(userInfo);
if (user ==null){
return null;
}
String token = JwtUtils.generateToken(new UserInfo(user.getId(),user.getUsername()),
properties.getPrivateKey(), properties.getExpire());
return token;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
这便是从登陆验证到生成token的过程了。初次登录后在token有效的时间内,我们都不是直接接收前端传来的username、password来判断用户了,而是直接获取token来检验,当然,token不一定非要放在cookie里,前端也可以每次请求的时候把token传过来。
那么这里就需要一个检验用户的接口,用以将token转化为用户信息。
用户检验
用户检验接口
/**
* 验证用户信息
* @param token
* @return
*/
@GetMapping("verify")
public Result verifyUser(@CookieValue("LY_TOKEN")String token){
try {
// 从token中解析token信息
UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.prop.getPublicKey());
// 解析成功返回用户信息
return new Result(true,StatusCode.OK,"",userInfo);
} catch (Exception e) {
e.printStackTrace();
}
// 出现异常则,响应错误
return new Result(false,StatusCode.ERROR,"");
}
刷新token
配置文件中写的token有效时间是30分钟,但是用户有可能一直在线,因此应该加上刷新token的机制,即再某个节点又重新覆盖一遍token。
前端对很多地方的操作都需要获取用户信息,因此我们在用户检验接口那里增加一个刷新操作。
/**
* 验证用户信息
* @param token
* @return
*/
@GetMapping("verify")
public Result verifyUser(@CookieValue("LY_TOKEN")String token,HttpServletRequest request, HttpServletResponse response){
try {
// 从token中解析token信息
UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.prop.getPublicKey());
// 解析成功要重新刷新token
token = JwtUtils.generateToken(userInfo, this.prop.getPrivateKey(), this.prop.getExpire());
// 更新cookie中的token
CookieUtils.setCookie(request, response, this.prop.getCookieName(), token, this.prop.getCookieMaxAge());
// 解析成功返回用户信息
return new Result(true,StatusCode.OK,"",userInfo);
} catch (Exception e) {
e.printStackTrace();
}
// 出现异常则,响应错误
return new Result(false,StatusCode.ERROR,"");
}
很多时候我们从token中获取用户信息只是前端的请求中的一部分需求,因此上述逻辑感觉封装在一个service里面的用处更大。
利用拦截器进行权限检验
很多时候我们不会专门去对每一个请求接口都加上这么一个用户信息检验这样的逻辑,那么这里我们就需要配置一个拦截器来对请求进行拦截。通过判断token来判断该请求是否是在登录状态发起的,如果不是登录状态,那就转发到登录界面让其登录。
拦截器:
通过实现springmvc的HandlerInterceptor接口来声明一个拦截器
@EnableConfigurationProperties(JwtProperties.class)
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
private JwtProperties properties;
@Override
public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) throws IOException {
String token = CookieUtils.getCookieValue(request, properties.getCookieName());
// 校验
try {
// 校验通过什么都不做,即放行
JwtUtils.getInfoFromToken(token, this.properties.getPublicKey());
} catch (Exception e) {
// 校验出现异常,返回403
response.sendRedirect("/auth/accredit");
return false;
}
return true;
}
/**
* 在请求被处理后,视图渲染之前调用
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 在整个请求结束后调用
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
注意照理来说我们就应该在这里加上一个@Component注解才对,这样在springmvc的配置类那里我们也可以直接调用来注册,但是现实告诉我那样会报错,会导致我们的资源文件JwtProperties加载不到我们在yml中的数据,然而controller中的数据依旧是能读取到的。
注册拦截器以及声明白名单:
先来了解一下WebMvcConfigurer这个接口
WebMvcConfigurer配置类其实是Spring内部的一种配置方式
采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制
基于java-based方式的spring mvc配置
需要创建一个配置类并实现WebMvcConfigurer 接口。
作用就和我们之前在xml中注册声明ssm的各项基本参数一样
@Configuration
public class LoginConfiguration implements WebMvcConfigurer {
@Bean
public LoginInterceptor loginInterceptor(){
return new LoginInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry){
// 注册拦截器
InterceptorRegistration loginRegistry = registry.addInterceptor(loginInterceptor());
// 拦截路径
loginRegistry.addPathPatterns("/**");
// 排除路径
loginRegistry.excludePathPatterns("/");
loginRegistry.excludePathPatterns("/auth/accredit");
/*loginRegistry.excludePathPatterns("/loginout");*/
// 排除资源请求
loginRegistry.excludePathPatterns("/css/login/*.css");
loginRegistry.excludePathPatterns("/js/login/**/*.js");
loginRegistry.excludePathPatterns("/image/login/*.png");
}
}
注意上面的@Bean形式声明的过滤器,这样才能让配置的加载都不出问题,才能让JwtProperties配置类读取到application.yml中的配置信息。这是由于拦截器的额加载是在springcontext之前的,所以要在这里来声明。
springboot使用jwt进行权限验证的更多相关文章
- SpringBoot集成JWT实现token验证
原文:https://www.jianshu.com/p/e88d3f8151db JWT官网: https://jwt.io/ JWT(Java版)的github地址:https://github. ...
- SpringBoot集成JWT实现权限认证
目录 一.JWT认证流程 二.SpringBoot整合JWT 三.测试 上一篇文章<一分钟带你了解JWT认证!>介绍了JWT的组成和认证原理,本文将介绍下SpringBoot整合JWT实现 ...
- Springboot Oauth2 集成Swagger2权限验证实战
Swagger是什么?能干什么?在这就不展开讲解了.本文主要讲解如何集成OAuth2的Password模式权限验证,验证接口是否具有权限. 引入依赖 <dependency> <gr ...
- SpringBoot整合Apache Shiro权限验证框架
比较常见的权限框架有两种,一种是Spring Security,另一种是Apache Shiro,两种框架各有优劣,个人感觉Shiro更容易使用,更加灵活,也更符合RABC规则,而且是java官方更推 ...
- springboot之JWT实现权限认证
1.在pom.xml添加依赖 <dependency> <groupId>com.auth0</groupId> <artifactId>java-jw ...
- SpringBoot 使用jwt进行身份验证
这里只供参考,比较使用jwt方式进行身份验证感觉不好,最不行的就是不能退出 登陆时设定多长过期时间,只能等这个时间过了以后才算退出,服务端只能验证请求过来的token是否通过验证 Code: /** ...
- webapi使用jwt做权限验证
考虑到很多公司目前并没有切换到.netcore,所有本文尝试使用.netframework下的webapi 首先使用Nuget 安装 jwt包 安装完成后,创建 jwt的帮助类 public clas ...
- springboot、springsecurity、jwt权限验证
1.背景 基于前后端分离项目的后端模块: 2.相关技术 springboot全家桶 web模块 security模块:用于权限的验证 mongodb 模块:集成mogodb模块 jwt 用于token ...
- SpringBoot集成JWT 实现接口权限认证
JWT介绍 Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的, 特别适用于分布式站点 ...
随机推荐
- WinForm的Socket实现简单的聊天室 IM
1:什么是Socket 所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象. 一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制. 从 ...
- 在SSM框架中如何将图片上传到数据库中
今天我们来看看SSM中如何将图片转换成二进制,最后传入到自己的数据库中,好了,废话不多说,我们开始今天的学习,我这里用的编辑器是IDEA 1.导入图片上传需要的jar依赖包 1 <depende ...
- Jenkins-k8s-helm-eureka-harbor-githab-mysql-nfs微服务发布平台实战
基于 K8S 构建 Jenkins 微服务发布平台 实现汇总: 发布流程设计讲解 准备基础环境 K8s环境(部署Ingress Controller,CoreDNS,Calico/Flannel) 部 ...
- 全网最详细的Linux命令系列-Find命令
Find工具实战 Find工具实战,Find工具主要用于操作系统文件.目录的查找,其语法参数格式为: find path -option [ -print ] [ -exec -ok command ...
- 2048小游戏(c++)(转)
下为源码 #include <iostream> #include <windows.h> #include <ctime> using namespace std ...
- Python基础(二十一):面向对象“类”第四课——魔法方法
先划一下重点: 6个魔法方法: 动态操作属性的4个函数: 魔法方法 魔法方法的简单介绍 魔法方法的命名规则:方法名(前后各有2个下划线). 通常情况下,不会主动去调用魔法方法,而是在满足一定的条件下, ...
- Java 使用 Maven BOM 统一管理版本号
一个中大型的 Java 项目往往包含若干 JAR 包,这些 JAR 包有着不同的版本号.如果这些 JAR 包单独发布,然后直接通过版本号引用相应的 JAR 包,不同版本的兼容性维护将变得十分麻烦.为了 ...
- Oracle-buffer cache过小导致SQL执行时间长
一.问题:客户反馈在生产库和测试库执行相同SQL,测试库执行比生产库慢一倍 问题摆在这里,需要进行分析? 啥??? 版本11.2.0.4,都是单实例,主机系统硬件配置差不多. 二.对比SQL的执行效率 ...
- JDK8之后,在java语言这条路怎么走?
前言 自2017年9月以来,Oracle按照免费的开源许可证(类似于Linux的许可证)提供JDK版本 .从Java SE 11(2018年9月,LTS)开始,Oracle不仅为开源许可下的所有用户免 ...
- 07_利用pytorch的nn工具箱实现LeNet网络
07_利用pytorch的nn工具箱实现LeNet网络 目录 一.引言 二.定义网络 三.损失函数 四.优化器 五.数据加载和预处理 六.Hub模块简介 七.总结 pytorch完整教程目录:http ...