Spring Security能解决问题,而且额外赠送所有Spring Security功能。
Token方法非常好,以下是如何使用spring-security保护API的步骤:
实现AuthenticationEntryPoint并将commence方法设置为401,而不是重定向3XX,具体如下:
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,"Access Denied")
- 创建一个TokenProcessingFilter,继承UsernamePasswordAuthenticationFilter的功能,重写doFilter()方法,从请求头中提取令牌,按以下步骤验证和认证令牌:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = this.getAsHttpRequest(request);
String authToken = this.extractAuthTokenFromRequest(httpRequest);
String userName = TokenUtils.getUserNameFromToken(authToken);
if (userName != null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
if (TokenUtils.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication =new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
你的Spring-security配置将如下所示:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthFailure authFailure;
@Autowired
private AuthSuccess authSuccess;
@Autowired
private EntryPointUnauthorizedHandler unauthorizedHandler;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationTokenProcessingFilter authTokenProcessingFilter;
@Autowired
public void configureAuthBuilder(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.addFilter(authTokenProcessingFilter)
.authorizeRequests()
.antMatchers("/resources/**", "/api/authenticate").permitAll()
.antMatchers("/persons").authenticated();
}
}
-- 最后,您需要另一个用于身份验证和令牌生成的终点。以下是一个Spring MVC示例。
@Controller
@RequestMapping(value="/api")
public class TokenGenerator{
@Autowired
@Lazy
private AuthenticationManager authenticationManager;
@Autowired
private UtilityBean utilityBean;
@Autowired
private UserDetailsService userDetailsService;
@RequestMapping(value="/authenticate", method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<?> generateToken(@RequestBody EmefanaUser user){
ResponseEntity<?> response = null;
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserId(),user.getCredential());
try {
Authentication authentication = authenticationManager.authenticate(authenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = userDetailsService.loadUserByUsername(user.getUserId());
String token = TokenUtils.createToken(userDetails);
response = ResponseEntity.ok(new TokenResource(utilityBean.encodePropertyValue(token)));
} catch (AuthenticationException e) {
response = ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
return response;
}
}
1 生成令牌,2. 后续的API调用应该带有令牌。是的,Spring Security可以做到这一点,您不必在身份验证和授权方面开创新的领域。