Springboot整合jwt token验证
笔记一下token验证。
1.所需依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
2. application.yml
## jwt配置
jwt:
# 密钥, 经过Base64加密, 可自行替换
secret: MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=
expire: 3600 # token有效时长
header: token # header 名称
3.JwtConfig
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
@ConfigurationProperties(prefix = "jwt")
@Component
@Getter
@Setter
public class JwtConfig {
private String secret;
private long expire;
private String header;
/**
* 生成token
* @param subject
* @return
*/
public String createToken (String subject){
Date nowDate = new Date();
Date expireDate = new Date(nowDate.getTime() + expire * 1000);//过期时间
return Jwts.builder()
.setHeaderParam("typ", "JWT")
.setSubject(subject)
.setIssuedAt(nowDate)
.setExpiration(expireDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
/**
* 获取token中注册信息
* @param token
* @return
*/
public Claims getTokenClaim (String token) {
try {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}catch (Exception e){
// e.printStackTrace();
return null;
}
}
/**
* 验证token是否过期失效
* @param expirationTime
* @return
*/
public boolean isTokenExpired (Date expirationTime) {
return expirationTime.before(new Date());
}
/**
* 获取token失效时间
* @param token
* @return
*/
public Date getExpirationDateFromToken(String token) {
return getTokenClaim(token).getExpiration();
}
/**
* 获取用户名从token中
*/
public String getUsernameFromToken(String token) {
return getTokenClaim(token).getSubject();
}
/**
* 获取jwt发布时间
*/
public Date getIssuedAtDateFromToken(String token) {
return getTokenClaim(token).getIssuedAt();
}
4.配置拦截器
import com.pdd.core.config.JwtConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.SignatureException;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class TokenInterceptor extends HandlerInterceptorAdapter {
@Autowired
private JwtConfig jwtConfig;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws SignatureException {
/** 地址过滤 */
String uri = request.getRequestURI() ;
//过滤生成token的接口
if (uri.contains("/pdd/test/getToken")){
return true ;
}
/** Token 验证 */
String token = request.getHeader(jwtConfig.getHeader());
if(StringUtils.isEmpty(token)){
token = request.getParameter(jwtConfig.getHeader());
}
if(StringUtils.isEmpty(token)){
throw new SignatureException(jwtConfig.getHeader()+ "不能为空");
}
Claims claims = null;
try{
claims = jwtConfig.getTokenClaim(token);
if(claims == null || jwtConfig.isTokenExpired(claims.getExpiration())){
throw new SignatureException(jwtConfig.getHeader() + "失效,请重新登录。");
}
}catch (Exception e){
throw new SignatureException(jwtConfig.getHeader() + "失效,请重新登录。");
}
/** 设置 identityId 用户身份ID */
request.setAttribute("identityId", claims.getSubject());
return true;
}
}
5.注册拦截器到SpringMvc
import com.pdd.core.interceptor.TokenInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private TokenInterceptor tokenInterceptor ;
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor).addPathPatterns("/pdd/test/**");
}
}
6.统一异常处理类
import com.pdd.core.pojo.ResultPoJo;
import io.jsonwebtoken.SignatureException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class PermissionHandler {
@ExceptionHandler(value = { SignatureException.class })
@ResponseBody
public ResultPoJo<?> authorizationException(SignatureException e){
return new ResultPoJo("4502", e.getMessage());
}
}
7.测试接口
@Api(tags = "测试token")
@RestController
@RequestMapping("/pdd/test/")
public class TestController {
@Autowired
private JwtConfig jwtConfig;
@ApiOperation(value = "获取token")
@GetMapping("/getToken")
public ResultPoJo getToken(@RequestParam("id") Integer userid){
String token = jwtConfig.createToken(String.valueOf(userid));
return new ResultPoJo(token);
}
@ApiOperation(value = "需要token的接口")
@PostMapping("/info")
public ResultPoJo getList(){
return new ResultPoJo("info");
}
}
8.postman测试
获取token
不用token访问接口
利用刚刚获取的token去访问接口