0
点赞
收藏
分享

微信扫一扫

SpringBoot+Spring Security和JWT的集成实现登陆授权认证

全栈顾问 2022-01-10 阅读 64

这两天做 SpringBoot+Spring Security和JWT的集成实现登陆授权认证 ,找了很多文章,看了很多的博客都不敬人意,终于功夫不负有心人,总算是把这个授权认证做好了,特此记录一下 。具体的原理我这就不做过多阐述,感兴趣的人可以自己去看相关的文章。下面直接上代码:

  • 导入对应依赖
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
  • 添加 token 工具类
/**
 * @author 
 * @version 1.0.0
 * @ClassName JWTUtil.java
 * @Description JWTUtil
 * @createTime 2022年01月09日 21:29:00
 */
@Component
public class JWTUtil implements Serializable {

    private static final long serialVersionUID = -916592859157433572L;

    private static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60;

    @Value("${jwt.secret}")
    private String secretKey;

    public String getUsernameFromToken(String token) {
        return getClaimFromToken(token, Claims::getSubject);
    }

    private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = getAllClaimsFromToken(token);
        return claimsResolver.apply(claims);
    }

    private Claims getAllClaimsFromToken(String token) {
        return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
    }

    private Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }

    private Date getExpirationDateFromToken(String token) {
        return getClaimFromToken(token, Claims::getExpiration);
    }

    public  String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        return doGenerateToken(claims, userDetails.getUsername());
    }

    private String doGenerateToken(Map<String, Object> claims, String subject) {
        return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000)).signWith(SignatureAlgorithm.HS512, secretKey).compact();
    }

    public Boolean validateToken(String token, UserDetails userDetails) {
        final String username = getUsernameFromToken(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }

    public static void main(String[] args) {

    }

}
  • 添加过滤器(实现登陆的认证和授权)
@Component
public class JwtFilter extends OncePerRequestFilter {

    @Autowired
    private JWTUtil jwtUtil;

    @Autowired
    UserDetailsServiceIml userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String authorization = request.getHeader("Authorization");
        String token = null;
        String username = null;
        
        //获取token
        if (null != authorization && authorization.startsWith("Bearer ")) {
            token = authorization.substring(7);
            username = jwtUtil.getUsernameFromToken(token);
        }

        // 认证授权
        if (null != username && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = userDetailsServiceIml.loadUserByUsername(username);

            if (jwtUtil.validateToken(token, userDetails)) {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

                usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
            else {
                try {
                    throw new ValidationException("token 过期");
                } catch (ValidationException e) {
                    e.printStackTrace();
                }
            }

        }

        filterChain.doFilter(request, response);
    }

}

  • 登陆实现
@Service
public class LoginUserServiceIml implements LoginUserService {

    @Autowired
    JWTUtil jwtUtil;

    @Autowired
    UserDetailsServiceIml userDetailsService;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public String login(LoginUser loginUser) throws Exception {
        try {
            authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            loginUser.getUsername(),
                            loginUser.getPassword()
                    )
            );
        } catch (BadCredentialsException e) {
            throw new Exception("用户或密码错误", e);
        }

        UserDetails userDetails = userDetailsService.loadUserByUsername(loginUser.getUsername());

        StringBuilder stringBuilder = new StringBuilder("Bearer ");
        stringBuilder.append(jwtUtil.generateToken(userDetails));

        return stringBuilder.toString();
    }

    @Override
    public boolean register(SysUser sysUser) {
        return false;
    }
}
  • WebSecurityConfigurer 配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //跨域放行
        http.authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll();

        //停掉 session
        http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.authorizeRequests()
                .antMatchers("/sys/api/**").permitAll();

        http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
    }

至此即完成jwt的相关配置

举报

相关推荐

0 条评论