我们设法完全按照OP中的描述进行工作,希望其他人可以使用该解决方案。这是我们所做的:
像这样设置安全上下文:
<security:http realm="Protected API" use-expressions="true" auto-config="false" create-session="stateless" entry-point-ref="CustomAuthenticationEntryPoint"> <security:custom-filter ref="authenticationTokenProcessingFilter" position="FORM_LOGIN_FILTER" /> <security:intercept-url pattern="/authenticate" access="permitAll"/> <security:intercept-url pattern="/**" access="isAuthenticated()" /></security:http><bean id="CustomAuthenticationEntryPoint" /><bean id="authenticationTokenProcessingFilter" > <constructor-arg ref="authenticationManager" /></bean>
如你所见,我们创建了一个自定义AuthenticationEntryPoint,401 Unauthorized如果我们的请求未在过滤器链中进行身份验证,则该自定义基本上只会返回一个AuthenticationTokenProcessingFilter。
CustomAuthenticationEntryPoint:public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized: Authentication token was either missing or invalid." ); }}AuthenticationTokenProcessingFilter:
public class AuthenticationTokenProcessingFilter extends GenericFilterBean { @Autowired UserService userService; @Autowired TokenUtils tokenUtils; AuthenticationManager authManager; public AuthenticationTokenProcessingFilter(AuthenticationManager authManager) { this.authManager = authManager; } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { @SuppressWarnings("unchecked") Map<String, String[]> parms = request.getParameterMap(); if(parms.containsKey("token")) { String token = parms.get("token")[0]; // grab the first "token" parameter // validate the token if (tokenUtils.validate(token)) { // determine the user based on the (already validated) token UserDetails userDetails = tokenUtils.getUserFromToken(token); // build an Authentication object with the user's info UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails((HttpServletRequest) request)); // set the authentication into the SecurityContext SecurityContextHolder.getContext().setAuthentication(authManager.authenticate(authentication)); } } // continue thru the filter chain chain.doFilter(request, response); }}显然,TokenUtils其中包含一些私有(且非常与案例有关)的代码,并且不能轻易共享。这是它的界面:
public interface TokenUtils { String getToken(UserDetails userDetails); String getToken(UserDetails userDetails, Long expiration); boolean validate(String token); UserDetails getUserFromToken(String token);}


