免费开源企业网站程序,平面设计平台接单,dede推荐评级网站模版,ipad可以做网站推广吗1.JWT是什么#xff1f; JWT#xff0c;英文全称JSON Web Token#xff1a;JSON网络令牌。为了在网络应用环境间传递声明而制定的一种基于JSON的开放标准(RFC 7519)。这个规范允许我们使用JWT在客户端和服务端之间传递安全可靠的信息。JWT是一个轻便的安全跨平台传输格式 JWT英文全称JSON Web TokenJSON网络令牌。为了在网络应用环境间传递声明而制定的一种基于JSON的开放标准(RFC 7519)。这个规范允许我们使用JWT在客户端和服务端之间传递安全可靠的信息。JWT是一个轻便的安全跨平台传输格式定义了一个紧凑自包含的方式用于通信双方之间作为 JSON 对象安全地传递信息。此信息可以通过数字签名进行验证和信任。 紧凑这个字符串简洁数据量小传输速度快能通过URL参数、HTTP请求提交的数据以及HTTP Header的方式进行传递。自包含负载中包含很多信息比如用户的ID等。别人拿到这个字符串就能拿到这些关键的业务信息从而避免再通过数据库查询等方式得到它们。 JWT的结构 JWT由三段信息用.连接构成的字符串。 Header.Payload.Signature 例如 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxIn0.ihOZFzg3ZGIbBMneRy-4RMqors1P3nuO-wRJnQtTzWQ Header头部 承载两部分信息token类型和采用的加密算法 { typ: JWT,alg: HS256
} token类型JWT 加密算法HS256 Payload负载 存放有效信息的地方 iss: jwt签发者 sub: jwt所面向的用户 aud: 接收jwt的一方 exp: 过期时间戳(jwt的过期时间这个过期时间必须要大于签发时间) nbf: 定义在什么时间之前该jwt都是不可用的 iat: jwt的签发时间 jti: jwt的唯一身份标识主要用来作为一次性token从而回避重放攻击 Signature签名 对头部及负载内容进行签证。采用Header中声明的算法接收三个参数base64编码的Header、base64编码的Payload和密钥secret进行运算。密钥secret是保存在服务端的服务端会根据这个密钥进行生成token和进行验证。 2.环境搭建 参考代码仓库里面的mysql模块这里只贴出docker-compose.yml version: 3
services:mysql:image: registry.cn-hangzhou.aliyuncs.com/zhengqing/mysql:5.7container_name: mysql_3306restart: unless-stopped volumes:- ./mysql/my.cnf:/etc/mysql/my.cnf- ./mysql/init-file.sql:/etc/mysql/init-file.sql- ./mysql/data:/var/lib/mysql
# - ./mysql/conf.d:/etc/mysql/conf.d- ./mysql/log/mysql/error.log:/var/log/mysql/error.log- ./mysql/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d # init sql script directory -- tips: it can be excute when /var/lib/mysql is emptyenvironment: # set environment,equals docker run -eTZ: Asia/ShanghaiLANG: en_US.UTF-8MYSQL_ROOT_PASSWORD: root # set root passwordMYSQL_DATABASE: demo # init database nameports: # port mappping- 3306:3306 运行 docker-compose -f docker-compose.yml -p mysql5.7 up -d 初始化表 DROP TABLE IF EXISTS jwt_user;
CREATE TABLE jwt_user(id varchar(32) CHARACTER SET utf8 NOT NULL COMMENT 用户ID,username varchar(100) CHARACTER SET utf8 NULL DEFAULT NULL COMMENT 登录账号,password varchar(255) CHARACTER SET utf8 NULL DEFAULT NULL COMMENT 密码
)ENGINE InnoDB CHARACTER SET utf8 COMMENT 用户表 ROW_FORMAT Compact;INSERT INTO jwt_user VALUES(1,admin,123); 3.代码工程 实验目标实现JWT的签发和验证 pom.xml ?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdspringboot-demo/artifactIdgroupIdcom.et/groupIdversion1.0-SNAPSHOT/version/parentmodelVersion4.0.0/modelVersionartifactIdjwt/artifactIdpropertiesmaven.compiler.source8/maven.compiler.sourcemaven.compiler.target8/maven.compiler.target/propertiesdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-autoconfigure/artifactId/dependency!--mysql--dependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.29/version/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-jdbc/artifactId/dependencydependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.5.1/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdcom.alibaba/groupIdartifactIdfastjson/artifactIdversion1.2.47/version/dependencydependencygroupIdio.jsonwebtoken/groupIdartifactIdjjwt/artifactIdversion0.9.1/version/dependencydependencygroupIdcom.auth0/groupIdartifactIdjava-jwt/artifactIdversion3.4.0/version/dependency/dependencies
/project application.yaml spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/demo?useSSLfalseuseUnicodetruecharacterEncodingUTF-8serverTimezoneGMTusername: rootpassword: rootserver:port: 8088 Jwt生成 package com.et.jwt.service;import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;import com.et.jwt.entity.User;
import org.springframework.stereotype.Service;import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;Service(TokenService)public class TokenService {long outHours1;public String getToken(User user) {Instant instant LocalDateTime.now().plusHours(outHours).atZone(ZoneId.systemDefault()).toInstant();Date expire Date.from(instant);String token;// save information to token ,such as: user id and Expires timetoken JWT.create().withAudience(user.getId()).withExpiresAt(expire).sign(Algorithm.HMAC256(user.getPassword()));// use HMAC256 to generate token,key is users passwordreturn token;}
} jwt验证 package com.et.jwt.interceptor;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;import com.et.jwt.annotation.PassToken;
import com.et.jwt.annotation.UserLoginToken;
import com.et.jwt.entity.User;
import com.et.jwt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Date;public class AuthenticationInterceptor implements HandlerInterceptor {AutowiredUserService userService;Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {// get token from http headerString token httpServletRequest.getHeader(token);if(!(object instanceof HandlerMethod)){return true;}HandlerMethod handlerMethod(HandlerMethod)object;Method methodhandlerMethod.getMethod();//check is included passtoken annotation? jump if haveif (method.isAnnotationPresent(PassToken.class)) {PassToken passToken method.getAnnotation(PassToken.class);if (passToken.required()) {return true;}}//check is included UserLoginToken ?if (method.isAnnotationPresent(UserLoginToken.class)) {UserLoginToken userLoginToken method.getAnnotation(UserLoginToken.class);if (userLoginToken.required()) {// excute verifyif (token null) {throw new RuntimeException(token invalidplease login again);}// get user id from tokenString userId;try {userId JWT.decode(token).getAudience().get(0);} catch (JWTDecodeException j) {throw new RuntimeException(401);}User user userService.findUserById(userId);if (user null) {throw new RuntimeException(user is not existplease login again);}// verify tokenJWTVerifier jwtVerifier JWT.require(Algorithm.HMAC256(user.getPassword())).build();try {jwtVerifier.verify(token);if (JWT.decode(token).getExpiresAt().before(new Date())) {throw new RuntimeException(token Expires);}} catch (JWTVerificationException e) {throw new RuntimeException(401);}return true;}}return true;}Overridepublic void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {}Overridepublic void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {}
} 以上只是一些关键代码所有代码请参见下面代码仓库 代码仓库 https://github.com/Harries/springboot-demo 4.测试 启动Spring Boot应用登录系统http://localhost:8088/api/login?usernameadminpassword123 {user: {username: admin,password: 123,id: 1},token: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxIn0.ihOZFzg3ZGIbBMneRy-4RMqors1P3nuO-wRJnQtTzWQ
} 在header里面设置 token访问http://localhost:8088/api/getMessage 5.引用 https://www.v2ex.com/t/817906http://www.liuhaihua.cn/archives/710374.htmlhttps://github.com/ChuaWi/SpringBoot-JWT/tree/master 6.Questions 这里留2个问题给读者 过期了如何刷新token呢保证过期时候重新登录而不是后台自动刷新一直不过期如果要实现强制下线用户功能该如何实现呢