Springboot基于注解鉴权
@Slf4j @Component public class ResourceInterceptor implements HandlerInterceptor { @Resource UserRoleService userRoleService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { User user = UserUtil.getUser(); if (user == null) { response.setStatus(401); return false; } Set<String> userRoles = new HashSet<>(userRoleService.userRole(user.getId())); if (handler instanceof HandlerMethod handlerMethod) { Method method = handlerMethod.getMethod(); boolean annotationPresent = method.isAnnotationPresent(HasRole.class); if (annotationPresent) { HasRole annotation = method.getAnnotation(HasRole.class); String[] roleRequire = annotation.roles(); for (String s : roleRequire) { if (userRoles.contains(s)) { return true; } } response.setStatus(401); return false; } } return true; } }
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HasRole {
String[] roles() default {};
}
@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Resource
private AuthenticationInterceptor authenticationInterceptor;
@Resource
private ResourceInterceptor resourceInterceptor;
private static final String[] EXCLUDE_PATHS = {};
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authenticationInterceptor)
.addPathPatterns("/api/**")
.order(10);
registry.addInterceptor(resourceInterceptor)
.excludePathPatterns(EXCLUDE_PATHS)
.addPathPatterns("/api/**")
.order(100);
}
}
@Slf4j
@Component
public class AuthenticationInterceptor implements HandlerInterceptor {
@Resource
JwtService jwtService;
@Resource
UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("Token");
if (token == null) {
return true;
}
if (token.startsWith("Bearer ")) {
token = token.substring(7);
}
String id;
try {
id = jwtService.extractClaim(token, c -> String.valueOf(c.get("id")));
} catch (ExpiredJwtException e) {
return true;
}
if (CheckUtil.isNumber(id)) {
UserUtil.setUser(userService.getUserById(Long.parseLong(id)));
return true;
}
return false;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
UserUtil.remove();
}
}
@Service public class JwtService { @Value("${jwt.key}") private String secretKey; @Value("${jwt.expiration}") private long jwtExpiration; public String extractUsername(String token) { return extractClaim(token, Claims::getSubject); } public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) { final Claims claims = extractAllClaims(token); return claimsResolver.apply(claims); } public String generateToken(User user) { return generateToken(new HashMap<>(), user); } public String generateToken(Map<String, Object> extraClaims, User user) { return buildToken(extraClaims, user, jwtExpiration); } public long getExpirationTime() { return jwtExpiration; } private String buildToken( Map<String, Object> extraClaims, User user, long expiration ) { return Jwts .builder() .setClaims(extraClaims) .setSubject(user.getUsername()) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(new Date(System.currentTimeMillis() + expiration)) .signWith(getSignInKey(), SignatureAlgorithm.HS256) .compact(); } public boolean isTokenValid(String token, User user) { final String username = extractUsername(token); return (username.equals(user.getUsername())) && !isTokenExpired(token); } private boolean isTokenExpired(String token) { return extractExpiration(token).before(new Date()); } private Date extractExpiration(String token) { return extractClaim(token, Claims::getExpiration); } private Claims extractAllClaims(String token) { return Jwts .parserBuilder() .setSigningKey(getSignInKey()) .build() .parseClaimsJws(token) .getBody(); } private Key getSignInKey() { byte[] keyBytes = Decoders.BASE64.decode(secretKey); return Keys.hmacShaKeyFor(keyBytes); } }
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.5</version> </dependency>
jwt:
key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
expiration: 86400000
使用
@HasRole(roles = {"admin"})