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"})

 

posted on 2024-09-11 14:43  lxxd  阅读(23)  评论(0编辑  收藏  举报

导航