SpringBoot与JWT
SpringBoot与JWT
Demo
项目结构
项目源码
Application
package com.supremepole.c02springbootjwt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan
@SpringBootApplication
public class C02SpringBootJwtApplication {
public static void main(String[] args) {
SpringApplication.run(C02SpringBootJwtApplication.class, args);
}
}
JwtController
package com.supremepole.c02springbootjwt;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @ClassName JwtController
* @Description
* @Date 2022/5/12 20:03
* @Version 1.0.0
**/
@RestController
public class JwtController {
@PostMapping("/get")
public String creatToken(){
User user = new User();
user.setId("1");
user.setUsername("SupremePole");
user.setPassword("https://cs.supremepole.com");
return JwtUtil.createJWT(40000,user);
}
@PostMapping("/test")
public String testToken(HttpServletRequest request, HttpServletResponse response){
String token= request.getHeader("Authorization");
User user = new User();
user.setId("1");
user.setUsername("SupremePole");
user.setPassword("https://cs.supremepole.com");
if (JwtUtil.isVerify(token,user)){
return "success";
}
return "fail";
}
}
JwtFilter
package com.supremepole.c02springbootjwt;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @ClassName JwtFilter
* @Description
* @Date 2022/5/12 20:04
* @Version 1.0.0
**/
@WebFilter(urlPatterns = "/testToken", filterName = "jwtFilter")
public class JwtFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
response.setHeader("Access-Control-Allow-Origin", "*");
String token= request.getHeader("Authorization");
User user = new User();
user.setId("1");
user.setUsername("SupremePole");
user.setPassword("https://cs.supremepole.com");
boolean flag = JwtUtil.isVerify(token,user);
if (flag){
filterChain.doFilter(servletRequest,servletResponse);
}else {
System.out.println("失败。。。。。。。。");
response.getWriter().write("失败。。。。。。。。");
}
}
@Override
public void destroy() {
}
}
JwtUtil
package com.supremepole.c02springbootjwt;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @ClassName JwtUtil
* @Description
* @Date 2022/5/12 20:03
* @Version 1.0.0
**/
public class JwtUtil {
/**
* 用户登录成功后生成Jwt
* 使用Hs256算法 私匙使用用户密码
*
* @param ttlMillis jwt过期时间
* @param user 登录成功的user对象
* @return
*/
public static String createJWT(long ttlMillis, User user) {
//指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//生成JWT的时间
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//创建payload的私有声明(根据特定的业务需要添加,如果要拿这个做验证,一般是需要和jwt的接收方提前沟通好验证方式的)
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("id", user.getId());
claims.put("username", user.getUsername());
claims.put("password", user.getPassword());
//生成签名的时候使用的秘钥secret
String key = user.getPassword();
//生成签发人
String subject = user.getUsername();
//下面就是在为payload添加各种标准声明和私有声明了
//这里其实就是new一个JwtBuilder,设置jwt的body
JwtBuilder builder = Jwts.builder()
//如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就覆盖了那些标准的声明
.setClaims(claims)
//设置jti(JWT ID):是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
.setId(UUID.randomUUID().toString())
//iat: jwt的签发时间
.setIssuedAt(now)
//代表这个JWT的主体
.setSubject(subject)
//设置签名使用的签名算法和签名使用的秘钥
.signWith(signatureAlgorithm, key);
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
//设置过期时间
builder.setExpiration(exp);
}
return builder.compact();
}
/**
* Token的解密
* @param token 加密后的token
* @param user 用户的对象
* @return
*/
public static Claims parseJWT(String token, User user) {
//签名秘钥,和生成的签名的秘钥一模一样
String key = user.getPassword();
//得到DefaultJwtParser
Claims claims = Jwts.parser()
//设置签名的秘钥
.setSigningKey(key)
//设置需要解析的jwt
.parseClaimsJws(token).getBody();
return claims;
}
/**
* 校验token
* 在这里可以使用官方的校验,我这里校验的是token中携带的密码于数据库一致的话就校验通过
* @param token
* @param user
* @return
*/
public static Boolean isVerify(String token, User user) {
//签名秘钥,和生成的签名的秘钥一模一样
String key = user.getPassword();
//Jwts.parser在执行parseClaimsJws(token)时如果token时间过期会抛出ExpiredJwtException异常
try {
//得到DefaultJwtParser
Claims claims = Jwts.parser()
//设置签名的秘钥
.setSigningKey(key)
//设置需要解析的jwt
.parseClaimsJws(token).getBody();
if (claims.get("password").equals(user.getPassword())) {
return true;
}
}catch (ExpiredJwtException e){
e.printStackTrace();
}
return false;
}
}
User
package com.supremepole.c02springbootjwt;
/**
* @ClassName User
* @Description
* @Date 2022/5/12 20:07
* @Version 1.0.0
**/
public class User {
private String id;
private String username;
private String password;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
application.properties
server.port=8087