前言

  相信大家在进行用户认证中或多或少都要对用户进行认证,当前进行认证的方式有基于session、token等主流方式,但是目前使用最广泛的还是基于JWT的用户认证,特别适用于前后端分离的项目。

本篇博客我将简要的讲解JWT(Json web token)的只要知识点并实现简单的认证,如果我哪些方面有问题,请大家激烈评论,我好进一步修改!

1.Jwt的组成

  将Jwt是由头部Header、载荷payload、以及签名sign三个部分组成

  1.1 Herder

     头部包含签名的生成token的'typ'以及'alo'也就是签名的类型和哪一种算法,还有签名中部分的编码格式

  1.1 payload

        载荷中存储部分用户的信息,但是最好不要将密码存储在载荷中,因为头部以及载荷安全性不高

  1.1 sign

     JWT的安全性体现在签名中,它是由头部、载荷以及盐进行Base64加密而成的,中间使用“.”连接,最后使用头部的编码格式编码得到签名。因为头部和载荷的安全性较低,所以我们主要通过盐来防止token伪造,一般通过

     HMAC256算法对其进行加密

2.Jwt的认证流程

  上述图详细地叙述了通过JWT进行认证的过程

  1)用户第一次在浏览器网页里面输入用户名和密码进行认证,当客户端收到用户信息后对用户信息进行验证

  2)客户端对用户信息验证无误后,返回一个token给浏览器

  3)用户下次登录的时候携带这个token进行登录

  4)客户端验证token无误后就放行

  5)服务端返回用户访问客户端资源

3.Jwt的实现

  3.1 生成token

private static final long EXPIRE_TIME = 1800L;//单位为秒
private static final String TOKEN_SECRET = "woToken"; /**
* 生成token
* @param sysUser
* @return
*/
public static String sign(SysUser sysUser){
String token = null; try {
Date expireDate = new Date(System.currentTimeMillis() + EXPIRE_TIME * 1000);
Map<String, Object> map = new HashMap<>();
map.put("alg", "HS256");
map.put("typ", "JWT");
token = JWT.create()
.withHeader(map)//添加头部
.withIssuer("auth0")
.withClaim("uid", sysUser.getUid())//载体中设置uid
.withClaim("username", sysUser.getUsername())//载体中设置username
.withExpiresAt(expireDate)//设置过期时间
.withIssuedAt(new Date())//设置签发时间
.sign(Algorithm.HMAC256(TOKEN_SECRET));//secret加密
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (JWTCreationException e) {
e.printStackTrace();
}
return token;
}

生成token

  3.2 验证token

/**
* 校验token并解析token
*/
public static Boolean verifyToken(String token){
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
DecodedJWT decodedJWT = verifier.verify(token);
return true;
} catch (JWTVerificationException e) {
e.printStackTrace();
return false;
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
}
}

验证token

  3.3 获取token中的uid

/**
* 获取token中的payload信息
* @param token
* @return
*/
public static Integer getUid(String token){
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("uid").asInt();
} catch (JWTDecodeException e) {
return null;
}
}

获取载荷信息

package com.ku.wo.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.ku.wo.entity.SysUser; import java.util.Date;
import java.util.HashMap;
import java.util.Map; /**
* 生成Jwt和认证
*/
public class JwtUtils { private static final long EXPIRE_TIME = 1800L;//单位为秒
private static final String TOKEN_SECRET = "woToken"; /**
* 生成token
* @param sysUser
* @return
*/
public static String sign(SysUser sysUser){
String token = null; try {
Date expireDate = new Date(System.currentTimeMillis() + EXPIRE_TIME * 1000);
Map<String, Object> map = new HashMap<>();
map.put("alg", "HS256");
map.put("typ", "JWT");
token = JWT.create()
.withHeader(map)//添加头部
.withIssuer("auth0")
.withClaim("uid", sysUser.getUid())//载体中设置uid
.withClaim("username", sysUser.getUsername())//载体中设置username
.withExpiresAt(expireDate)//设置过期时间
.withIssuedAt(new Date())//设置签发时间
.sign(Algorithm.HMAC256(TOKEN_SECRET));//secret加密
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (JWTCreationException e) {
e.printStackTrace();
}
return token;
} /**
* 校验token并解析token
*/
public static Boolean verifyToken(String token){
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
DecodedJWT decodedJWT = verifier.verify(token);
return true;
} catch (JWTVerificationException e) {
e.printStackTrace();
return false;
} catch (IllegalArgumentException e) {
e.printStackTrace();
return false;
}
} /**
* 获取token中的payload信息
* @param token
* @return
*/
public static Integer getUid(String token){
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("uid").asInt();
} catch (JWTDecodeException e) {
return null;
}
} }

JWT生成、校验、获取载荷信息全部代码

  3.4 拦截请求

package com.ku.wo.interceptor;

import com.ku.wo.utils.JwtUtils;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* 用于获取token并校验
*/ /**
* 单体项目验证token使用拦截器,分布式项目使用网关
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// //不使用JWT使用的登录
//// if (request.getSession().getAttribute("uid") == null){
//// return false;//如果这里为false,后面的都不执行,并且postHandle()方法也不执行
//// }
//// return true; if(HttpMethod.OPTIONS.toString().equals(request.getMethod())){
System.out.println("OPTIONS请求,放行!");
return true;
} String token = request.getSession().getAttribute("token").toString();
System.out.println("拦截器的token获取"+token);
// String token = request.getHeader("token");
if(JwtUtils.verifyToken(token)){
return true;
}
//失败时返回失败信息
return false;
}
}

拦截请求

  3.5 拦截资源

package com.ku.wo.config;

import com.ku.wo.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.ArrayList;
import java.util.List; @Configuration
public class WebConfig implements WebMvcConfigurer { @Autowired(required = false)
LoginInterceptor loginInterceptor; @Override
public void addInterceptors(InterceptorRegistry registry) {
//创建拦截器对象 //白名单
List<String> patterns = new ArrayList<>();
patterns.add("/user/reg");
patterns.add("/user/login");
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")//默认对所有请求进行拦截
.excludePathPatterns(patterns);
} }

拦截资源

  3.6 controller执行

@PostMapping("/login")//在浏览器上面应该改为get
public JsonResult<String> login(@RequestParam(value = "name", required = false) String username,
@RequestParam(value = "pwd", required = false) String password, HttpSession session){
SysUser data = userDetailsService.login(username, password);
String token = JwtUtils.sign(data);
session.setAttribute("token", token);
session.setAttribute("user", data);
session.setAttribute("uid",data.getUid());
session.setAttribute("username", username);
return new JsonResult<String>(OK, token);
} @PostMapping("/get_login_data")//在浏览器上面应该改为get
public JsonResult<SysUser> getLoginData(String token, HttpSession session){
if(!session.getAttribute("token").equals(token)){
return new JsonResult<>(ERROR);
}
SysUser data = (SysUser)session.getAttribute("user");
return new JsonResult<SysUser>(OK, data);
} //JSONResult响应类
package com.ku.wo.utils; import lombok.Data; import java.io.Serializable; @Data
//原文使用的是<E>因为属性data属于元素,但是我在网上找到使用T貌似更好,
// 尝试一下使用T的情况怎么样,List<T>表示集合中元素都为T类型,网上使用的大多数也是T
public class JsonResult<T> implements Serializable {
private Integer state;
private String message;
private T data;
//必须要有无参构造
public JsonResult(){
super();
}
public JsonResult(Integer state){
super();
this.state = state;
} public JsonResult(Throwable e){//Throwable是error和Exception的父类,里面有getMessage()方法获取错误和异常信息
super();
this.message = e.getMessage();
} public JsonResult(Integer state, T data){
super();
this.state = state;
this.data = data;
}
}

controller测试方法

4.Jwt测试

5.参考链接

https://blog.csdn.net/m0_56966142/article/details/123398543?ops_request_misc=&request_id=&biz_id=102&utm_term=%E4%BD%BF%E7%94%A8JWT%E5%AE%9E%E7%8E%B0%E7%94%A8%E6%88%B7%E8%AE%A4%E8%AF%81&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-0-123398543.142^v63^control_1,201^v3^control_2,213^v2^t3_esquery_v2&spm=1018.2226.3001.4187

Springboot整合Jwt实现用户认证的更多相关文章

  1. SpringBoot整合JWT实现登录认证

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

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

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

  3. Node.js 使用JWT进行用户认证

    代码地址如下:http://www.demodashi.com/demo/13847.html 运行环境 该项目基于 node(v7.8.0版本以上) 和 mongodb 数据库,因此电脑上需要安装这 ...

  4. ASP.NET Core 2.2 : 二十六. 应用JWT进行用户认证

    本文将通过实际的例子来演示如何在ASP.NET Core中应用JWT进行用户认证以及Token的刷新方案(ASP.NET Core 系列目录) 一.什么是JWT? JWT(json web token ...

  5. 应用JWT进行用户认证及Token的刷新

    本文将通过实际的例子来演示如何在ASP.NET Core中应用JWT进行用户认证以及Token的刷新方案(ASP.NET Core 系列目录) 一.什么是JWT? JWT(json web token ...

  6. ASP.NET Core 2.2 : 二十六. 应用JWT进行用户认证及Token的刷新

    来源:https://www.cnblogs.com/FlyLolo/p/ASPNETCore2_26.html 本文将通过实际的例子来演示如何在ASP.NET Core中应用JWT进行用户认证以及T ...

  7. DRF使用JWT进行用户认证

    1. 首先需要安装第三方依赖包 pip install djangorestframework-jwt 2. 在Django的settings文件中 配置全局的JWT认证类 REST_FRAMEWOR ...

  8. 教你 Shiro + SpringBoot 整合 JWT

    本篇文章将教大家在 shiro + springBoot 的基础上整合 JWT (JSON Web Token) 如果对 shiro 如何整合 springBoot 还不了解的可以先去看我的上一篇文章 ...

  9. 前后端分离下用jwt做用户认证

    0 前后端分离下的用户信息认证 前端使用Vue+axios,后端使用SpringBoot+SpringSecurity. 为了解决http无状态的问题,我采用jwt(json web token)保存 ...

  10. SpringBoot整合Shiro 四:认证+授权

    搭建环境见: SpringBoot整合Shiro 一:搭建环境 shiro配置类见: SpringBoot整合Shiro 二:Shiro配置类 shiro整合Mybatis见:SpringBoot整合 ...

随机推荐

  1. 工作随笔1-从slave备份,恢复成新得从库

    innobackupex --slave-info --safe-slave-backup --no-timestamp tmp_lastinnobackupex --apply-log tmp_la ...

  2. vue项目如何配置路由

    vue3项目中如何配置路由 1.下载vue-router,在路由文件中引入相关依赖 import {createRouter,createWebHashHistory} from 'vue-route ...

  3. centos 通过yum安装docker-ce报错

    通过yum安装docker-ce报错,是因为本机安装过多次造成的,如下所示,需要解决掉冲突依赖,从新安装 1 从 https://mirrors.aliyun.com/docker-ce/linux/ ...

  4. (粗糙版)DeptDao,Service

    DeptDao package com.javasm.dao; import com.javasm.bean.Dept; import com.javasm.util.JDBCUtils; impor ...

  5. MySQL count(*) 和 count(字段) 区别

    count(字段)不会取Null的 select count(*) from test01                7条 select count(0) from test01          ...

  6. P1706 全排列问题(DFS)

    全排列问题 题目描述 按照字典序输出自然数1到n所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字. 输入格式 一个整数n 输出格式 由1 ~ n组成的所有不重复的数字序列 ...

  7. CUDA基础2

    二. 1.指令调度,对于多条指令怎样调度让他们运行更快. 对于有冲突的两条指令,采用寄存器重命名技术. 2.指令重排  乱序执行,为了获取最大的吞吐率.  增大功耗 增加芯片面积. 3.缓存,容量越大 ...

  8. DVWA-File Inclusion(文件包含)

    文件包含漏洞,当我们在一个代码文件想要引入.嵌套另一个代码文件的时候,就是文件包含. 常见的文件包含函数有include require等函数. 这两个函数的区别就是include在包含文件不存在时p ...

  9. sql处理重复的列,更好理清分组和分区

    一.分组统计.分区排名 1.语法和含义: 如果查询结果看得有疑惑,看第二部分-sql处理重复的列,更好理清分组和分区,有建表插入数据的sql语句 分组统计:GROUP BY 结合 统计/聚合函数一起使 ...

  10. 对利用jsp模板编写登录、注册界面的方法言

    使用模板的相关操作步骤详解 1.可以在相关的网站上面找相关的css或者js文件,下载到一个特定的文件夹里面,以备使用 2.然后,将存有相关代码的文件夹直接复制粘贴到web文件下,就会直接保存,可以根据 ...