博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot 整合 JWT 实现统一认证
阅读量:2094 次
发布时间:2019-04-29

本文共 6359 字,大约阅读时间需要 21 分钟。

JWT官网:

参考:

JWT是什么?

JWT(Json Web Token)是为了在网络应用环境间传递声明而执行的一种基于 Json 的开放标准。JWT 的声明一般被用来在身份提供者服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。

比如用在用户登录上时,基本思路就是用户提供用户名和密码给认证服务器,服务器验证用户提交信息的合法性;如果验证成功,会产生并返回一个 Token,用户可以使用这个 Token 访问服务器上受保护的资源。

JWT的组成

JWT 由三部分构成,第一部分称为头部(Header),第二部分称为消息体(Payload),第三部分是签名(Signature)。一个 JWT 生成的 Token 格式为:

token = encodeBase64(header) + '.' + encodeBase64(payload) + '.' + encodeBase64(signature)

注意需要使用Base64对称加密,否则鉴权中心无法解密。

头部的信息通常由两部分内容组成,令牌的类型和使用的签名算法,比如下面的代码:

{

  "alg": "HS256", 
  "typ": "JWT"
}

消息体中可以携带一些你需要的信息,比如用户 ID。因为你得知道这个 Token 是哪个用户的,比如下面的代码:

{

  "id": "666", 
  "name": "biandan", 
  "blog": “”
}

签名是用来判断消息在传递的路上是否被篡改,从而保证数据的安全性,格式如下:

HMACSHA256( base64UrlEncode(header)  + "." +  base64UrlEncode(payload), secret)

实现需求:用户登录成功后,使用 JWT 生成 token 返回给前端,前端拿到 token 后,如果需要调用后台接口,需要把 token 放在头部的 Authorization,否则鉴权不通过。

OK,我们创建一个 SpringBoot 项目。为了方便起见,直接把用户名和密码写到配置里。实际项目应该是从数据库或者 Redis 里读取。并且把 sessionId 也放在内存里,实际项目应该是放在 Redis 缓存里。

pom.xml 

4.0.0
com.study
study-jwt
1.0-SNAPSHOT
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
com.auth0
java-jwt
3.15.0
org.springframework.cloud
spring-cloud-dependencies
Hoxton.SR2
pom
import

配置文件 application.yml

server:  port: 80# 将SpringBoot项目作为单实例部署调试时,不需要注册到注册中心eureka:  client:    fetch-registry: false    register-with-eureka: false# JWT 加解密的秘钥myJwt:  password: 666666# 用户信息,暂时从配置文件读取,理论上应该从数据库、Redis里读取userInfo:  userName: biandan  password: 123456  userSign: 让天下没有难写的代码!

启动类:

package com.study;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * @author biandan * @description * @signature 让天下没有难写的代码 * @create 2021-06-25 下午 7:20 */@SpringBootApplicationpublic class JwtApp {    public static void main(String[] args) {        SpringApplication.run(JwtApp.class, args);    }}

控制层 :

package com.study.controller;import com.auth0.jwt.JWT;import com.auth0.jwt.JWTVerifier;import com.auth0.jwt.algorithms.Algorithm;import com.auth0.jwt.interfaces.Claim;import org.springframework.beans.factory.annotation.Value;import org.springframework.http.HttpStatus;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;import java.util.Collections;import java.util.Date;import java.util.HashMap;import java.util.Map;/** * @author biandan * @description * @signature 让天下没有难写的代码 * @create 2021-06-25 下午 7:21 */@RestControllerpublic class LoginController {    //从配置文件获取用户信息,理论上应该从数据库或者Redis,为了方便学习    @Value("${userInfo.userName}")    private String userName;    @Value("${userInfo.password}")    private String password;    @Value("${userInfo.userSign}")    private String userSign;    //JWT 加解密的秘钥    @Value("${myJwt.password}")    private String jwtPassword;    //保存 sessionId-sign,理论上应该保存到 Redis    private static Map
userInfoMap = Collections.synchronizedMap(new HashMap<>()); //登录接口,登录成功后返回 token @PostMapping("/login") public Map
login(HttpServletRequest request) { Map
result = new HashMap<>(); String userName = request.getParameter("userName"); String password = request.getParameter("password"); if (this.userName.equals(userName) && this.password.equals(password)) { String sessionId = request.getSession().getId(); //使用 JWT 生成 token String token = getToken(sessionId, userName); result.put("data", token); result.put("code", HttpStatus.OK.value()); result.put("msg", "登录成功"); } else { result.put("code", HttpStatus.FORBIDDEN.value()); result.put("msg", "账号或密码不对,登录失败!"); } return result; } //使用 JWT 生成token private String getToken(String sessionId, String userName) { HashMap
map = new HashMap<>(); map.put("alg", "HS256"); map.put("typ", "JWT"); String token = JWT.create() .withHeader(map) .withClaim("sessionId", sessionId) //存入 sessionId .withClaim("userName", userName)//存入 userName .withIssuedAt(new Date()) .sign(Algorithm.HMAC256(jwtPassword)); System.out.println("登录 sessionId=" + sessionId); System.out.println("登录 token=" + token); userInfoMap.put(sessionId, userSign);//存放session-用户的个性签名 return token; } //鉴权,鉴权成功我们返回用户信息 @PostMapping("/getUserInfo") public Map
getUserInfo(HttpServletRequest request) { Map
result = new HashMap<>(); String token = request.getHeader("Authorization"); if (!StringUtils.isEmpty(token)) { JWTVerifier verifier = JWT.require(Algorithm.HMAC256(jwtPassword)).build(); Map
map = verifier.verify(token).getClaims(); if (null != map) { String sessionId = map.get("sessionId").asString();//取出 sessionId String userSign = userInfoMap.get(sessionId); String userName = map.get("userName").asString();//取出 userName System.out.println("对应的userName=" + userName); result.put("data", userSign); result.put("code", HttpStatus.OK.value()); result.put("msg", "SUCCESS"); return result; } } result.put("code", HttpStatus.UNAUTHORIZED.value()); result.put("msg", "账号未登录,请重新登录!"); return result; }}

启动,使用 postman 测试:

1、测试登录接口:

2、继续测试 getUserInfo 接口,把刚才后台返回的 data 数据(就是 token )复制出来,在 Headers 里的 key 选择 Authorization,value 就是 token 值。

OK,测试通过。

转载地址:http://nkuhf.baihongyu.com/

你可能感兴趣的文章
两年Java程序员面试经
查看>>
面试心得与总结---BAT、网易、蘑菇街
查看>>
如何面试有2年java工作经验的应聘人员
查看>>
Java实现简单的递归操作
查看>>
Java实现简单的递归操作
查看>>
Struts2工作原理和执行流程图
查看>>
在线预览Word,Excel~
查看>>
hibernate延迟加载(get和load的区别)
查看>>
关于文件拷贝效率问题
查看>>
MyBatis分页插件PageHelper的使用
查看>>
【MyBatis学习01】宏观上把握MyBatis框架
查看>>
【MyBatis学习02】走进MyBatis的世界
查看>>
【MyBatis学习03】原始dao开发方法及其弊端
查看>>
【MyBatis学习04】mapper代理方法开发dao
查看>>
【MyBatis学习05】SqlMapConfig.xml文件中的配置总结
查看>>
【MyBatis学习06】输入映射和输出映射
查看>>
【MyBatis学习07】动态sql
查看>>
【MyBatis学习08】高级映射之一对一查询
查看>>
【MyBatis学习09】高级映射之一对多查询
查看>>
【MyBatis学习10】高级映射之多对多查询
查看>>