Spring 通过 REST 端点的安全性 authentication/authorization

Spring Security authentication/authorization via REST endpoint

在我的 Spring 带有 RESTful 网络服务的启动应用程序中,我配置了 Spring 安全以及 Spring 社交和 SpringSocialConfigurer

现在我有两种方式 authentication/authorization - 通过 username/password 和社交网络,例如 Twitter。

为了在我的 Spring MVC REST 控制器中通过我自己的 RESTful 端点实现 authentication/authorization 我添加了以下方法:

@RequestMapping(value = "/login", method = RequestMethod.POST)
public Authentication login(@RequestBody LoginUserRequest userRequest) {
    Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userRequest.getUsername(), userRequest.getPassword()));
    boolean isAuthenticated = isAuthenticated(authentication);
    if (isAuthenticated) {
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }
    return authentication;
}

private boolean isAuthenticated(Authentication authentication) {
    return authentication != null && !(authentication instanceof AnonymousAuthenticationToken) && authentication.isAuthenticated();
}

但我不确定在 /login 端点调用成功后必须返回给客户端的确切内容。我认为返回完整的身份验证对象是多余的。

如果身份验证成功,应该返回给客户端什么?

能否请您告诉我如何正确实现此登录方法?

另外,如果是 RESTfull 登录,我会有 UsernamePasswordAuthenticationToken,如果通过 Twitter 登录,我会有 SocialAuthenticationToken同一个应用程序?

Restful 调用应始终 return 响应代码。在您的情况下,它应该只是 200 OK。失败时 401 未经授权。有不同的令牌是绝对没问题的,无论如何你不能使用相同的。

我个人更愿意通过 Spring 安全过滤器而不是控制器来处理登录端点,因为您可以更好地控制流程。

您可以通过重写 SimpleUrlAuthenticationSuccessHandler

中的方法来配置成功验证后要 return 的内容
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    public CustomAuthenticationSuccessHandler() {
        super();
        setRedirectStrategy(new NoRedirectStrategy());
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {

        super.onAuthenticationSuccess(request, response, authentication);
        ObjectMapper mapper = new ObjectMapper();

        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().print(mapper.writeValueAsString(objectToBereturned);
        response.getWriter().flush();
    }

    protected class NoRedirectStrategy implements RedirectStrategy {

        @Override
        public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
                throws IOException {
            // any redirect if required. leave the implementation black if not needed
        }

    }
}

此外,您还可以处理失败响应:


public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException exception) throws IOException, ServletException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    }
}