实现思路:
- 用户登录请求登录接口时,验证用户名密码等,验证成功会返回给前端一个token,这个token就是之后鉴权的唯一凭证。
- 后台可能将token存储在redis或者数据库中。
- 之后前端的请求,需要在header中携带token,后端取出token去redis或者数据库中进行验证,如果验证通过则放行,如果不通过则拒绝操作。
当然,如上的说法只是简单的实现,实质上还有很多需要优化的地方。
可以参考:https://blog.csdn.net/kkkun_joe/article/details/81878231
https://www.javamall.com.cn/blog/archives/642
具体实现方式
1、添加依赖
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example.jwt.token</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2、生成签名方法
/** * 生成签名 */ public String sign(String userName,String passWord){ Date date=new Date(System.currentTimeMillis()+3600); //设置私钥和加密算法 Algorithm algorithm=Algorithm.HMAC256("sadfsfsf3r3r545dfdfasas"); //设置头部信息 Map<String,Object> header=new HashMap<>(); header.put("typ","JWT"); header.put("alg","HS256"); String token = JWT.create().withHeader(header).withClaim("userName", userName) .withClaim("passWord", passWord).withExpiresAt(date).sign(algorithm); return token; }
3、解码,通过token获取用户名
/** * 通过token获取用户 * @param token */ @GetMapping("/user/{token}") public void getUserName(@PathVariable("token") String token){ String userName = JWT.decode(token).getClaim("userName").asString(); System.out.println(userName); }
4、增加拦截器
public class LoginInterceptor implements HandlerInterceptor { @Autowired private LoginController loginController; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("token"); if(StringUtils.isEmpty(token)){ throw new Exception("token不能为空"); } Boolean verify = null; try { LoginController loginController=new LoginController(); verify = loginController.verify(token); if(verify){ return true; }else { return false; } } catch (Exception e) { return false; } } }
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/login") ; } }
5、测试
@GetMapping("/login") public String login(){ //模拟用户名和密码 String userName="admin"; String passWord="admin"; String token = sign(userName, passWord); return token; }