通过REST端点实现Spring Security身份验证/授权

10

在我的Spring Boot应用程序中,我已经配置了Spring Security以及Spring Social和SpringSocialConfigurer来实现RESTful web服务。

目前我有两种身份验证/授权方式——通过用户名/密码和通过社交网络,例如Twitter。

为了通过我的自己的RESTful端点在Spring MVC REST控制器中实现身份验证/授权,我添加了以下方法:

@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端点后应该向客户端返回什么。 我认为返回完整的身份验证对象是多余的。

在身份验证成功的情况下,应向客户端返回什么?

请告诉我如何正确实现此登录方法。

此外,在RESTful登录的情况下,我将拥有UsernamePasswordAuthenticationToken,而在通过Twitter登录的情况下,我将拥有SocialAuthenticationToken。在同一应用程序中使用不同的令牌是否可以接受?

2个回答

6
您可以通过覆盖SimpleUrlAuthenticationSuccessHandler中的方法来配置成功身份验证后返回的内容。
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);
    }
}

感谢您的回答。这正是我目前应用程序所使用的。 - alexanoid
似乎在Spring Boot 2.x中NoRedirectStrategy不可用,我应该从哪里获取它? - Leonid Dashko
1
@LeonidDashko NoRedirectStrategy 不是由 spring 提供的。它是我对 RedirectStrategy 接口的实现。您可以在上面的代码中找到相同的内容。有一个受保护的 NoRedirectStrategy 类,它实现了 RedirectStrategy 接口。但是,如果你不想使用它,你可以使用由 spring 提供的 DefaultRedirectStrategy - Akhil Bojedla

1
Restful调用应始终返回响应代码。在您的情况下,它应该只是200 OK。失败时为401未经授权。拥有不同的令牌是完全可以的,反正您也无法使用相同的令牌。
我个人更喜欢通过Spring Security过滤器处理登录端点,而不是控制器,因为您可以更好地控制流程。

有没有关于如何通过Spring Security过滤器处理登录端点的文档或指南? - rastadrian
肯定有。您可以搜索Spring Security Java配置示例,并查找自定义身份验证入口实现或登录过滤器。这里有一个例子:http://blog.jdriven.com/2014/10/stateless-spring-security-part-2-stateless-authentication/ - Vaelyr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接