请先阅读, 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