使用RESTWeb服务进行Spring安全登录

使用RESTWeb服务进行Spring安全登录,spring,spring-mvc,spring-security,spring-data,spring-webflow,Spring,Spring Mvc,Spring Security,Spring Data,Spring Webflow,我有一个SpringMVC web应用程序,它需要使用SpringSecurity对RESTfulWeb服务进行身份验证。我需要通过rest客户端访问同一个应用程序 这是我需要实现的 接受头是application/json(对于java rest客户端) 成功登录后,将以json格式向rest客户端发送一个令牌(或sessionId) 登录失败后,将以json格式发送错误消息 用于web请求 成功登录后,它将重定向到一个成功的jsp页面 登录失败后,将向同一loin页面发送错误消息 如

我有一个SpringMVC web应用程序,它需要使用SpringSecurity对RESTfulWeb服务进行身份验证。我需要通过rest客户端访问同一个应用程序

这是我需要实现的

接受头是application/json(对于java rest客户端)

  • 成功登录后,将以json格式向rest客户端发送一个令牌(或sessionId)

  • 登录失败后,将以json格式发送错误消息

用于web请求

  • 成功登录后,它将重定向到一个成功的jsp页面

  • 登录失败后,将向同一loin页面发送错误消息

如何使用spring mvc和spring security做到这一点?我做这件事的时间非常少,任何人请给我一个spring-security.xml的例子


谢谢

请考虑实现自定义AuthenticationSuccessHandler和AuthenticationFailureHandler,如下所述

您可能还需要实现一些简单的控制器,您将从AuthenticationHandler重定向到这些控制器。关于如何在Spring中实现REST身份验证,有很多建议。所以我相信结合这两个答案会给你一个解决方案

public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        // get accept headers from request
        // Redirect successfully logged in user to another url depending on the accept headers) 
        // put session id in response if needed
        ((WebAuthenticationDetails)SecurityContextHolder.getContext().getAuthentication().getDetails()).getSessionId();            
        String targetUrl = ""; //TODO insert here
        response.sendRedirect(targetUrl);
    }
}

public class AuthenticationFailureHandlerImpl extends SimpleUrlAuthenticationFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        // get accept headers from request
        // set failure url      
        // Do redirecting job
        setDefaultFailureUrl(FAILURE_URL);
        super.onAuthenticationFailure(request, response, exception);
    }   
}
在security.xml中

<http entry-point-ref="loginUrlAuthenticationEntryPoint" access-denied-page="/WEB-INF/views/errors/error403.jsp" access-decision-manager-ref="accessDecisionManager">
        ...
    <custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER"/>
        ...
</http>

<!-- Login filter and entry point -->   
<beans:bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <beans:property name="loginFormUrl" value="/signin" /></beans:bean>
    <beans:bean id="loginFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <beans:property name="authenticationManager"        ref="authenticationManager"/>
    <beans:property name="filterProcessesUrl"           value="/j_spring_security_check"/>
    <beans:property name="authenticationSuccessHandler" ref="authSuccessHandler"/>
    <beans:property name="authenticationFailureHandler" ref="authFailureHandler"/></beans:bean>
    <!-- Login filter and entry point -->          
    <beans:bean id="authSuccessHandler" class="com.example.security.AuthenticationSuccessHandlerImpl"/>    
    <beans:bean id="authFailureHandler" class="com.example.security.AuthenticationFailureHandlerImpl"/>            
</beans:beans>

...
...

我的建议如下。您可以使用标准web安全性来调用RESTFul服务,首先使用用户和密码进行身份验证并获取cookie,如果使用基于java的服务器,则在后续rest调用时将其作为cookie发送给服务器。我写的是SpringJava代码,它可以为您获取会话cookies。 不需要单独的json服务来获取令牌

public class RestAuthClient {
    String baseUrl = "http://localhost:8888/ecom";
    public String authenticateGetCookie(String user, String password){
        HttpMessageConverter<MultiValueMap<String, ?>> formHttpMessageConverter = new FormHttpMessageConverter();

        HttpMessageConverter<String> stringHttpMessageConverternew = new StringHttpMessageConverter();

        List<HttpMessageConverter<?>> messageConverters = new LinkedList<HttpMessageConverter<?>>();

        messageConverters.add(formHttpMessageConverter);
        messageConverters.add(stringHttpMessageConverternew);
        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
        map.add("j_username", user);
        map.add("j_password", password);

        String authURL = baseUrl+"/j_spring_security_check";
        RestTemplate restTemplate = new RestTemplate();

        restTemplate.setMessageConverters(messageConverters);

        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(map,
                requestHeaders);

        ResponseEntity<String> result = restTemplate.exchange(authURL, HttpMethod.POST, entity, String.class);
        HttpHeaders respHeaders = result.getHeaders();      
        System.out.println(respHeaders.toString());

        System.out.println(result.getStatusCode());

        String cookies = respHeaders.getFirst("Set-Cookie");
        return cookies;
    }
    public void setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
    }
}
公共类重新授权客户端{
字符串baseUrl=”http://localhost:8888/ecom";
公共字符串AuthenticatGetCookie(字符串用户、字符串密码){
HttpMessageConverter formHttpMessageConverter=新formHttpMessageConverter();
HttpMessageConverter stringHttpMessageConverternew=新的StringHttpMessageConverter();
列表>();
添加(formHttpMessageConverter);
添加(stringHttpMessageConverternew);
MultiValueMap=新链接的MultiValueMap();
添加(“j_用户名”,用户);
地图。添加(“j_密码”,密码);
字符串authURL=baseUrl+“/j_spring_security_check”;
RestTemplate RestTemplate=新RestTemplate();
restemplate.setMessageConverters(messageConverters);
HttpHeaders requestHeaders=新的HttpHeaders();
requestHeaders.setContentType(MediaType.APPLICATION\u FORM\u URLENCODED);
HttpEntity=新的HttpEntity(映射,
请求头);
ResponseEntity result=restemplate.exchange(authURL、HttpMethod.POST、entity、String.class);
HttpHeaders respHeaders=result.getHeaders();
System.out.println(respHeaders.toString());
System.out.println(result.getStatusCode());
字符串cookies=respHeaders.getFirst(“设置Cookie”);
归还饼干;
}
公共void setBaseUrl(字符串baseUrl){
this.baseUrl=baseUrl;
}
}

这被视为失败。REST客户端是无状态的,不知道表单身份验证。只有基于页眉的auth才能工作。谢谢Michael,你提出了一个非常好的观点。我已经更新了答案,不过不管怎样,测试一下还是不错的。立即重新思考你的逻辑。这不是REST的工作方式。REST是无状态的,您需要基于头的身份验证,如Basic、Digest和Negotiate。客户端甚至浏览器将完成其余的工作。