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被设计为紧凑且安全的, 特别适用于分布式站点 ...
随机推荐
- imagemagick 之 Fred's ImageMagick Scripts 在Ubuntu 下的实践
Fred's ImageMagick Scripts 官网:http://www.fmwconcepts.com/imagemagick/index.php Windows 10 (64-bit) u ...
- CSS篇-dispaly、position、定位机制、布局、盒子模型、BFC
display常用值 参考链接英文参考链接中文 // 常用值 none:元素不显示 inline:将元素变为内联元素,默认 block:将元素变为块级元素 inline-block:将元素变为内联块级 ...
- Python读写配置文件模块--Configobj
一.介绍 我们在项目的开发过程中应该会遇到这样的问题:我们的项目读取某个配置文件,然后才能按照配置的信息正常运行服务,当我们需要对修改服务的某些信息时,可以直接修改这个配置文件,重启服务即可,不用再去 ...
- springMVC:校验框架:多规则校验,嵌套校验,分组校验;ssm整合技术
知识点梳理 课堂讲义 学习目标 能够阐述表单验证的分类和区别 能够运用表单验证的常用注解 能够编写表单验证的示例 能够编写SSM整合的应用案例 能够总结SSM整合的步骤 1 校验框架 1.1 入门-视 ...
- Python的多进程和多线程
进程和线程 进程是系统进行资源分配的最小单位,线程是系统进行调度执行的最小单位: 一个应用程序至少包含一个进程,一个进程至少包含一个线程: 每个进程在执行过程中拥有独立的内存空间,而一个进程中的线程之 ...
- 计算机体系结构——CH4 输入输出系统
计算机体系结构--CH4 输入输出系统 右键点击查看图像,查看清晰图像 X-mind 计算机体系结构--CH4 输入输出系统 输入输出原理 特点 实时性 与设备无关性 异步性 输入输出系统的组织方式 ...
- Kubernetes声明式API与编程范式
声明式API vs 命令时API 计算机系统是分层的,也就是下层做一些支持的工作,暴露接口给上层用.注意:语言的本质是一种接口. 计算机的最下层是CPU指令,其本质就是用"变量定义+顺序执行 ...
- 【10.5NOIP普及模拟】sort
[10.5NOIP普及模拟]sort 文章目录 [10.5NOIP普及模拟]sort 题目描述 输入 输出 输入输出样例 样例输入 样例输出 数据范围限制 解析 code 题目描述 小x和小y是好朋友 ...
- 一文彻底搞定Hystrix!
前言 Netflix Hystrix断路器是什么? Netflix Hystrix是SOA/微服务架构中提供服务隔离.熔断.降级机制的工具/框架.Netflix Hystrix是断路器的一种实现,用于 ...
- Kubernetes 学习笔记-- kafka往couchdb里倒东西
首先吐槽下国内这些论坛的技术精神,不是我崇洋媚外,有些复读机烦不烦啊,别人的东西吃进去吐出来好玩么? 还有一些不懂装懂,这种最可恶,明明自己都不明白自己在写什么,还是往精华区发,简直离谱,知道自己多挣 ...