使用RESTWeb服务进行Spring安全登录
我有一个SpringMVC web应用程序,它需要使用SpringSecurity对RESTfulWeb服务进行身份验证。我需要通过rest客户端访问同一个应用程序 这是我需要实现的 接受头是application/json(对于java rest客户端)使用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页面发送错误消息 如
- 成功登录后,将以json格式向rest客户端发送一个令牌(或sessionId)
- 登录失败后,将以json格式发送错误消息
- 成功登录后,它将重定向到一个成功的jsp页面
- 登录失败后,将向同一loin页面发送错误消息
谢谢请考虑实现自定义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。客户端甚至浏览器将完成其余的工作。