使用 SpringBoot 提供 api 的时候,我更喜欢使用 jwt 的方式来做验证。网上有会多 Spring Security 整合 jwt 的,也有 Shiro 整合 jwt 的,感觉有点复杂。这里分享一下自己在项目中的简单实现。
依赖包
除了 SpringBoot 基本的依赖,需要一个生成 jwt 和序列化的包。生成 jwt 的包依赖很多,因为我项目里使用了 hutool 这个包,就只用用它了。
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.9</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.9</version>
</dependency>
jwt用户模型
定义一个 Jwt 的 sub 字段模型,存储用户:
import lombok.Data;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Data
public class JwtUser {
/**
* 用户编号
*/
private Integer id;
/**
* 用户名
*/
private String name;
/**
* 角色
*/
private String role;
/**
* 获取当前请求用户
* @return
*/
public static JwtUser getCurrentUser() {
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
return (JwtUser) request.getAttribute("user");
}
}
验证注解
定义一个用于请求类和方法的注解
import java.lang.annotation.*;
@Inherited
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Authorize {
/**
* 是否匿名可以访问
* @return
*/
boolean anonymous() default false;
/**
* 角色
* @return
*/
String[] roles() default {};
}
JWT 帮助类
用于生成 jwt 和 解析 JwtUser 对象。
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.google.gson.Gson;
import com.mpyf.xapi.security.JwtUser;
import lombok.var;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class JwtTokenUtils {
public static final String SECRET = "your_secret";
public static final String ISS = "com.your.cn";
private static final int EXPIRATIONHOURS = 24; //过期时间24小时
//创建token
public static String createToken(JwtUser user) {
return createToken(user, EXPIRATIONHOURS);
}
public static String createToken(JwtUser user, int hours) {
String subJson = new Gson().toJson(user);
JWTSigner jwtSigner = JWTSignerUtil.hs512(SECRET.getBytes());
JWT jwt = JWT.create().setSigner(jwtSigner);
jwt
.setJWTId(UUID.randomUUID().toString().replace("-", ""))
.setSubject(subJson) //用户信息
.setIssuer(ISS) //签发者
//.setAudience("受众")
//.setNotBefore(new Date())
.setIssuedAt(new Date())
.setExpiresAt(new Date(System.currentTimeMillis() + hours * 3600 * 1000));
return jwt.sign();
}
public static JwtUser getUser(String token) {
if (StringHelper.isNullOrEmpty(token)) return null;
var jwt = JWTUtil.parseToken(token);
JWTSigner jwtSigner = JWTSignerUtil.hs512(SECRET.getBytes());
jwt.setSigner(jwtSigner);
if (jwt.validate(10)) {
var subJson = jwt.getPayload("sub").toString();
JwtUser user = new Gson().fromJson(subJson, JwtUser.class);
return user;
} else {
return null