服务端开发实战Spring-BootSpring Boot

Spring Boot用3个class轻松实现JWT (三) 鉴

2018-01-23  本文已影响814人  JonTian

请先阅读, Spring Boot用3个class轻松实现JWT (一), 保护你的RESTful API
基于前两部分略做扩展, 和Spring Security集成在了一起.
实现了@PreAuthorize的功能
https://github.com/ZhongjunTian/spring-boot-jwt-demo/tree/master/spring-security-jwt

    @GetMapping("/api/admin")
    @PreAuthorize("hasAuthority('ADMIN_USER')")
    public @ResponseBody
    Object helloToAdmin(String userId) {
        return "Hello World! You are ADMIN ";
    }

和Spring Security集成在一起, 首先要配置, 和前面文章的思想一样, 我们要允许所有/login的请求, 只对其他请求验证权限

Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers(HttpMethod.POST, "/login").permitAll()
                .anyRequest().authenticated()
                .and()
                // We filter the api/** requests
                .addFilterBefore(new JwtAuthenticationFilter(),
                        UsernamePasswordAuthenticationFilter.class);
    }
}

配置好了之后, 只需要将之前在Spring Boot用3个class轻松实现JWT (一)那篇文章中提到的JwtAuthenticationFilter添加一行代码, 将用户的Role信息注入进去, 然后下一个Filter, 也就是UsernamePasswordAuthenticationFilter就可以得到用户的信息. 这里生成的UsernamePasswordAuthenticationToken的前两个入参用户名和密码是null, 因为我们已经鉴定过jwt了, 只需要用这个token鉴权.

public class JwtAuthenticationFilter extends OncePerRequestFilter {
  //......一些不重要的代码......
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            if (isProtectedUrl(request)) {
                Map<String, Object> claims = JwtUtil.validateTokenAndGetClaims(request);
                String role = String.valueOf(claims.get(ROLE));
                //最关键的部分就是这里, 我们直接注入了Role信息
                SecurityContextHolder.getContext().setAuthentication(
                        new UsernamePasswordAuthenticationToken(
                                null, null, Arrays.asList(() -> role)));
            }
        } catch (Exception e) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
            return;
        }
        filterChain.doFilter(request, response);
    }
  //......一些不重要的代码......
}

我们用账号user, 密码user拿到普通权限的jwt之后, 就只能用/api/hello, 而/api/admin则会被spring security拦截报403错


主要参考了一下两篇文章, 精简了70%代码
https://github.com/nydiarra/springboot-jwt
http://www.baeldung.com/spring-security-oauth-jwt

上一篇 下一篇

猜你喜欢

热点阅读