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被设计为紧凑且安全的, 特别适用于分布式站点 ...
随机推荐
- 归一化(Normalization)和标准化(Standardization)
归一化和标准化是机器学习和深度学习中经常使用两种feature scaling的方式,这里主要讲述以下这两种feature scaling的方式如何计算,以及一般在什么情况下使用. 归一化的计算方式: ...
- 《逆向工程核心原理》Windows消息钩取
DLL注入--使用SetWindowsHookEx函数实现消息钩取 MSDN: SetWindowsHookEx Function The SetWindowsHookEx function inst ...
- 使用C# (.NET Core) 实现观察者模式 (Observer Pattern) 并介绍 delegate 和 event
观察者模式 这里面综合了几本书的资料. 需求 有这么个项目: 需求是这样的: 一个气象站, 有三个传感器(温度, 湿度, 气压), 有一个WeatherData对象, 它能从气象站获得这三个数据. 还 ...
- Python数据分析入门(一):搭建环境
Python版本: 本课程用到的Python版本都是3.x.要有一定的Python基础,知道列表.字符串.函数等的用法. Anaconda: Anaconda(水蟒)是一个捆绑了Python.cond ...
- 面试题-你听过TCP Fast Open (TFO/TCP快速打开)吗?能解释一下吗?
TCP Fast Open (TFO/TCP快速打开) TCP快速打开(TCP Fast Open,TFO)是什么? TCP快速打开(TCP Fast Open,TFO)是对TCP的一种简化握手手续的 ...
- Python函数参数和注解是什么
四种参数 Python函数func定义如下: def func(first, *args, second="Hello World", **kwargs): print(first ...
- HCL实验8:NAT搭建私有网络
NAT 通过NAT技术,进行私有网络的搭建 拓扑图 先对路由器的端口进行配置 R1 [H3C]sys R1 [R1]INT G0/0 [R1-GigabitEthernet0/0]ip address ...
- Dynamics CRM的Associate功能
Dynamics CRM有一种特殊的关联关系叫Associate,一般常见于为用户分配角色.给团队添加用户.团队添加角色.队列添加用户等等.在一些特定场景下我们不可能把所有的操作都通过手动来完成尤其是 ...
- (Set, Map, Collections工具类)JAVA集合框架二
Java集合框架部分细节总结二 Set 实现类:HashSet,TreeSet HashSet 基于HashCode计算元素存放位置,当计算得出哈希码相同时,会调用equals判断是否相同,相同则拒绝 ...
- Leedcode算法专题训练(字符串)
4. 两个字符串包含的字符是否完全相同 242. Valid Anagram (Easy) Leetcode / 力扣 可以用 HashMap 来映射字符与出现次数,然后比较两个字符串出现的字符数量是 ...