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来判断该请求是否是在登录状态发起的,如果不是登录状态,那就转发到登录界面让其登录。

拦截器:

通过实现springmvcHandlerInterceptor接口来声明一个拦截器

@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进行权限验证的更多相关文章

  1. SpringBoot集成JWT实现token验证

    原文:https://www.jianshu.com/p/e88d3f8151db JWT官网: https://jwt.io/ JWT(Java版)的github地址:https://github. ...

  2. SpringBoot集成JWT实现权限认证

    目录 一.JWT认证流程 二.SpringBoot整合JWT 三.测试 上一篇文章<一分钟带你了解JWT认证!>介绍了JWT的组成和认证原理,本文将介绍下SpringBoot整合JWT实现 ...

  3. Springboot Oauth2 集成Swagger2权限验证实战

    Swagger是什么?能干什么?在这就不展开讲解了.本文主要讲解如何集成OAuth2的Password模式权限验证,验证接口是否具有权限. 引入依赖 <dependency> <gr ...

  4. SpringBoot整合Apache Shiro权限验证框架

    比较常见的权限框架有两种,一种是Spring Security,另一种是Apache Shiro,两种框架各有优劣,个人感觉Shiro更容易使用,更加灵活,也更符合RABC规则,而且是java官方更推 ...

  5. springboot之JWT实现权限认证

    1.在pom.xml添加依赖 <dependency> <groupId>com.auth0</groupId> <artifactId>java-jw ...

  6. SpringBoot 使用jwt进行身份验证

    这里只供参考,比较使用jwt方式进行身份验证感觉不好,最不行的就是不能退出 登陆时设定多长过期时间,只能等这个时间过了以后才算退出,服务端只能验证请求过来的token是否通过验证 Code: /** ...

  7. webapi使用jwt做权限验证

    考虑到很多公司目前并没有切换到.netcore,所有本文尝试使用.netframework下的webapi 首先使用Nuget 安装 jwt包 安装完成后,创建 jwt的帮助类 public clas ...

  8. springboot、springsecurity、jwt权限验证

    1.背景 基于前后端分离项目的后端模块: 2.相关技术 springboot全家桶 web模块 security模块:用于权限的验证 mongodb 模块:集成mogodb模块 jwt 用于token ...

  9. SpringBoot集成JWT 实现接口权限认证

    JWT介绍 Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的, 特别适用于分布式站点 ...

随机推荐

  1. 归一化(Normalization)和标准化(Standardization)

    归一化和标准化是机器学习和深度学习中经常使用两种feature scaling的方式,这里主要讲述以下这两种feature scaling的方式如何计算,以及一般在什么情况下使用. 归一化的计算方式: ...

  2. Java例题_30 在已经排好序的数组中插入值

    1 /*30 [程序 30 插入数字] 2 题目:有一个已经排好序的数组.现输入一个数,要求按原来的规律将它插入数组中. 3 程序分析:首先判断此数是否大于最后一个数,然后再考虑插入中间的数的情况,插 ...

  3. 20182217_刘洪宇 后门原理与实践 EXP2

    1.后门概念 后门就是不经过正常认证流程而访问系统的通道. 哪里有后门呢? 编译器留后门 操作系统留后门 最常见的当然还是应用程序中留后门 还有就是潜伏于操作系统中或伪装为特定应用的专用后门程序. - ...

  4. [深搜]C. 【例题3】虫食算

    C . [ 例 题 3 ] 虫 食 算 题目解析 正解 : Dfs + 剪枝 依题意,把样例以加法的形式展现出来. 根据加法的性质,可以得出有两种情况:有进位和没有进位的. 而从百位到最高位的结果,又 ...

  5. cordova app打包apk签名

    首先执行:ionic cordova build android --prod --release,执行完会在以下目录生成apk文件( --prod 用以压缩) 然后使用keytool生成keysto ...

  6. java面试-内存分配与回收策略

    1.对象优先在Eden分配 -Xms20M -Xmx20M java堆的大小20M -Xmn10M 新生代10M 老年代10M -XX:SurvivorRatio=8 新生代Eden与一个Surviv ...

  7. JavaScript深入理解-正则表达式

    正则表达式 正则表达式是用于匹配字符串中字符组合的模式.在JavaScript中,正则表达式也是对象.这些模式被用于RegExp的 exec和 text方法,以及String中的 match.matc ...

  8. 详解DNS重绑定攻击

    0x00 前言 DNS重绑定攻击的用法有很多种,这篇文章主要理解DNS重绑定攻击的原理,并介绍如何通过DNS重绑定来攻击内网设备.为了更好的理解DNS重绑定攻击,我们先从Web浏览器的同源策略开始介绍 ...

  9. C++运算符重载的一些困惑

    一.背景 在复习<C++基础与提高>时,自己实现运算符重载(i++)时,几次都报错.其实还是自己对运算符重载这一部分内容理解得不够透彻,于是再次看了下书上的内容,理解算是加深了一些,于是提 ...

  10. pytorch从入门到放弃(目录)

    目录 前置基础 Pytorch从入门到放弃 推荐阅读 前置基础 Python从入门到放弃(目录) 人工智能(目录) Pytorch从入门到放弃 01_pytorch和tensorflow的区别 02_ ...