springboot+jwt实现token登陆权限认证的实现

作者:知识追寻者 时间:2021-12-22 12:02:46 

一 前言

此篇文章的内容也是学习不久,终于到周末有时间码一篇文章分享知识追寻者的粉丝们,学完本篇文章,读者将对token类的登陆认证流程有个全面的了解,可以动态搭建自己的登陆认证过程;对小项目而已是个轻量级的认证机制,符合开发需求;

二 jwt实现登陆认证流程

  • 用户使用账号和面发出post请求

  • 服务器接受到请求后使用私钥创建一个jwt,这边会生成token

  • 服务器返回这个jwt给浏览器

  • 浏览器需要将带有token的jwt放入请求头

  • 每次手到客户端请求,服务器验证该jwt的token

  • 验证成功返回响应的资源给浏览器。否则异常处理

三 相关介绍jwt

3.1jwt 组成

JWT的token由三段信息构成的,将这三段信息文本用.连接一起就构成了JWT字符串;

  • Header 头部(包含了令牌的元数据,并且包含签名和或加密算法的类型)

  • Payload 负载

  • Signature 签名/签证

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1ODI4OTc4NDUsInVzZXJuYW1lIjoienN6eHoifQ.vyiExkFWCCmQA3PFYL0jJfIiYGWubngqB0WcgmtHOxg

3.2 jwt优点

  • 简洁(Compact): 可以通过URL,POST参数或者在HTTP header发送,数据量小,传输速度快

  • 自包含(Self-contained):负载中包含了所有用户所需要的信息,避免多次查询数据库

  • .因为Token是以JSON加密的形式保存在客户端的,所以JWT是跨语言支持;

  • 不需要在服务端保存会话信息,适用于分布式与微服务;

四 jwt用户登陆发放token

4.1 pom.xml

项目构件如下

  • springboot 2.1;

  • jwt 3.4.0;

  • maven 3.5

  • jdk1.8

  • postman接口测试


<dependencies>
 <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
  <groupId>com.auth0</groupId>
  <artifactId>java-jwt</artifactId>
  <version>3.4.0</version>
 </dependency>
 <dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <optional>true</optional>
 </dependency>
</dependencies>

4.2jwt工具类

jwt工具类中有三个方法,分别是生成数字签名用于用户首次登陆时发送jwt给客户端;其次是校验方法,用于 * 拦截所有规则内的url,每个请求都必须带有服务器发送的jwt,经过验证后才放行请求;最后一个获得用户名的方法用于查询密钥,在验证jwt时作为参数传入;


/* *
* @Author lsc
* <p> JWT工具类 </p>
* @Param
* @Return
*/
public class JwtUtil {

// Token过期时间30分钟
public static final long EXPIRE_TIME = 30 * 60 * 1000;

/* *
* @Author lsc
* <p> 校验token是否正确 </p>
* @Param token
* @Param username
* @Param secret
* @Return boolean
*/
public static boolean verify(String token, String username, String secret) {
try {
// 设置加密算法
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm)
 .withClaim("username", username)
 .build();
// 效验TOKEN
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception exception) {
return false;
}
}

/* *
* @Author lsc
* <p>生成签名,30min后过期 </p>
* @Param [username, secret]
* @Return java.lang.String
*/
public static String sign(String username, String secret) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
Algorithm algorithm = Algorithm.HMAC256(secret);
// 附带username信息
return JWT.create()
.withClaim("username", username)
.withExpiresAt(date)
.sign(algorithm);

}

/* *
* @Author lsc
* <p> 获得用户名 </p>
* @Param [request]
* @Return java.lang.String
*/
public static String getUserNameByToken(HttpServletRequest request) {
String token = request.getHeader("token");
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("username")
.asString();
}
}

4.3 用户实体

实体中包含用户名,和密码,一切从简;


/**
* @Author lsc
* <p> </p>
*/
@Data
public class SysUser {
private String username;
private String password;
}

4.4Controller

表现层代码用户用户登陆认证,认证成功后发放token给客户端;


/**
* @Author lsc
* <p> </p>
*/
@RestController
public class SysUserController {

@PostMapping(value = "/login")
public Map<String, Object> login(@RequestBody SysUser sysUser){
 Map<String, Object> map = new HashMap<>();
 String username = sysUser.getUsername();
 String password = sysUser.getPassword();
 // 省略 账号密码验证
 // 验证成功后发送token
 String token = JwtUtil.sign(username,password);
 if (token != null){
  map.put("code", "200");
  map.put("message","认证成功");
  map.put("token", token);
  return map;
 }
 map.put("code", "403");
 map.put("message","认证失败");
 return map;
}
}

4.5 测试

测试url http://localhost:8080/login

postman post请求测试参数如下


{
"username": "zszxz",
"password": "zszxz"
}

返回内容如下


{
"code": "200",
"message": "认证成功",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1ODI4OTc4NDUsInVzZXJuYW1lIjoienN6eHoifQ.vyiExkFWCCmQA3PFYL0jJfIiYGWubngqB0WcgmtHOxg"
}

五 jwt登陆拦截认证

基于前面已经实现jwt登录认证后发放token给客户端;本节内容就是将token放入请求头中发送请求给服务器;服务器使用 * 拦截请求对token进行验证;验证成功请求通过,否则请求资源失败;

5.1自定义 *

自定义 * JwtInterceptor,实现HandlerInterceptor接口,每次请求到达之前都会验证token是否有效;


/**
* @Author lsc
* <p>token验证 * </p>
*/
@Component
public class JwtInterceptor implements HandlerInterceptor {

@Autowired
SysUserService sysUserService;

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 // 从 http 请求头中取出 token
 String token = request.getHeader("token");
 // 如果不是映射到方法直接通过
 if(!(handler instanceof HandlerMethod)){
  return true;
 }
 if (token != null){
  String username = JwtUtil.getUserNameByToken(request);
  // 这边拿到的 用户名 应该去数据库查询获得密码,简略,步骤在service直接获取密码
  boolean result = JwtUtil.verify(token,username,sysUserService.getPassword());
  if(result){
   System.out.println("通过 * ");
   return true;
  }
 }
 return false;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

}
}

5.2 service


/**
* @Author lsc
* <p> 模拟查询数据库获得账号密码 </p>
*/
@Service
public class SysUserService {

public String getPassword(){
 return "zszxz";
}
}

5.3 * 配置

* 配置中主要定义拦截请求规则,将 * 注入WebMvcConfigurer;cors跨域处理;


/* *
* @Author lsc
* <p> * 配置 </p>
* @Param
* @Return
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

/* *
 * @Author lsc
 * <p> 设置拦截路径 </p>
 * @Param [registry]
 * @Return void
 */
@Override
public void addInterceptors(InterceptorRegistry registry) {
 registry.addInterceptor(authenticationInterceptor())
   .addPathPatterns("/**")
   .excludePathPatterns("/login");
}
/* *
 * @Author lsc
 * <p> 将 * 注入context </p>
 * @Param []
 * @Return com.zszxz.jwt.interceptor.JwtInterceptor
 */
@Bean
public JwtInterceptor authenticationInterceptor() {
 return new JwtInterceptor();
}

/* *
 * @Author lsc
 * <p>跨域支持 </p>
 * @Param [registry]
 * @Return void
 */
@Override
public void addCorsMappings(CorsRegistry registry) {
 registry.addMapping("/**")
   .allowedOrigins("*")
   .allowCredentials(true)
   .allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS", "HEAD")
   .maxAge(3600 * 24);
}
}

5.4Controller

表现层接口用于拦截亲求测试


/**
* @Author lsc
* <p> </p>
*/
@RestController
public class TestController {

@GetMapping(value = "/api/test")
public String get(){

return "zszxz";
}
}

5.5 测试

测试url http://localhost:8080/api/test

发送get请求给服务器,带有请求头,key为token,value为用户首次登陆时返回的token串;

测试返回内容如下

zszxz

六 官网链接

https://jwt.io/introduction/

来源:https://blog.csdn.net/youku1327/article/details/104564953

标签:springboot,jwt,token,登陆
0
投稿

猜你喜欢

  • 使用SpringBoot获取resources文件路径

    2022-10-12 15:29:56
  • 浅析Android Service中实现弹出对话框的坑

    2023-04-20 16:17:13
  • Docker学习之基于Dockerfile搭建JAVA Tomcat运行环境的方法

    2022-02-13 17:42:00
  • jvm调优的几种场景(小结)

    2023-04-11 18:37:04
  • Java的Hibernate框架结合MySQL的入门学习教程

    2021-10-18 04:48:20
  • Maven打包没有指定主类问题(xxx.jar中没有主清单属性)

    2023-11-26 21:34:44
  • JAVAsynchronized原理详解

    2023-05-17 12:18:32
  • 详谈hibernate,jpa与spring data jpa三者之间的关系

    2022-08-04 22:35:57
  • C# 如何调用C++ dll string类型返回

    2023-01-31 02:27:55
  • JavaWeb开发中alias拦截器的使用方法

    2023-08-20 10:36:55
  • 关于C#委托三种调用的分享使用

    2022-10-29 03:24:35
  • Java动态获取实现某个接口下所有的实现类对象集合

    2023-04-01 14:43:20
  • C#中FormClosing与FormClosed的区别详细解析

    2023-01-26 16:28:13
  • spring boot RestTemplate 发送get请求的踩坑及解决

    2022-01-19 16:08:09
  • 深入理解 Java、Kotlin、Go 的线程和协程

    2022-05-04 12:39:14
  • Java实现的不同图片居中剪裁生成同一尺寸缩略图功能示例

    2023-08-23 14:53:15
  • Java设计模式之共享模式/享元模式(Flyweight模式)介绍

    2023-06-15 04:35:10
  • 解决Java中properties文件编码问题

    2022-07-21 14:09:06
  • c#滚动字幕动画窗体制作步骤

    2023-12-06 20:12:58
  • Spring security权限配置与使用大全

    2022-03-05 15:37:21
  • asp之家 软件编程 m.aspxhome.com