使用RestTemplate Spring安全认证
java spring 认证authentication 安全spring-security
我有提供2个独立的一整套服务2 Spring的web应用程序。 Web应用程序1具有Spring Security的使用认证。 现在,Web应用程序2需要访问Web应用程序1的服务。通常情况下,我们的RestTemplate类来发送请求到其他网络服务。 我们如何通过在Web应用程序2要求的身份验证凭据到Web应用程序1
本文地址 :CodeGo.net/238843/
-------------------------------------------------------------------------------------------------------------------------
1. 我当时的情况。这里有我的解决方案。 服务器-春季安全配置
rest.password}" authorities="ROLE_USER"/>
客户端端RestTemplate配置
rest.username}"/>
rest.password}"/>
自定义的HttpState
/**
* Custom implementation of {@link HttpState} with credentials property.
*
* @author banterCZ
*/
public class CustomHttpState extends HttpState {
/**
* Set credentials property.
*
* @param credentials
* @see #setCredentials(org.apache.commons.httpclient.auth.AuthScope, org.apache.commons.httpclient.Credentials)
*/
public void setCredentials(final Credentials credentials) {
super.setCredentials(AuthScope.ANY, credentials);
}
}
Maven的依赖
commons-httpclient
commons-httpclient
3.1
2. 这里是一个解决方案,它工作得很好,春季3.1和Apache HttpComponents 4.1我创建了这个网站为基础的答案和阅读的springRestTempalte源代码。我在救人的希望分享我觉得spring应该只是有这样的内置代码,但它没有。
RestClient client = new RestClient();
client.setApplicationPath("someApp");
String url = client.login("theuser", "123456");
UserPortfolio portfolio = client.template().getForObject(client.apiUrl("portfolio"),
UserPortfolio.class);
下面是设置了HttpComponents上下文是工厂类上与RestTemplate每个请求。
public class StatefullHttpComponentsClientHttpRequestFactory extends
HttpComponentsClientHttpRequestFactory
{
private final HttpContext httpContext;
public StatefullHttpComponentsClientHttpRequestFactory(HttpClient httpClient, HttpContext httpContext)
{
super(httpClient);
this.httpContext = httpContext;
}
@Override
protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri)
{
return this.httpContext;
}
}
下面是有状态的rest模板,你的cookies,一旦你与它会将JSESSIONID登录并发送它在后续的请求。
public class StatefullRestTemplate extends RestTemplate
{
private final HttpClient httpClient;
private final CookieStore cookieStore;
private final HttpContext httpContext;
private final StatefullHttpComponentsClientHttpRequestFactory statefullHttpComponentsClientHttpRequestFactory;
public StatefullRestTemplate()
{
super();
httpClient = new DefaultHttpClient();
cookieStore = new BasicCookieStore();
httpContext = new BasicHttpContext();
httpContext.setAttribute(ClientContext.COOKIE_STORE, getCookieStore());
statefullHttpComponentsClientHttpRequestFactory = new StatefullHttpComponentsClientHttpRequestFactory(httpClient, httpContext);
super.setRequestFactory(statefullHttpComponentsClientHttpRequestFactory);
}
public HttpClient getHttpClient()
{
return httpClient;
}
public CookieStore getCookieStore()
{
return cookieStore;
}
public HttpContext getHttpContext()
{
return httpContext;
}
public StatefullHttpComponentsClientHttpRequestFactory getStatefulHttpClientRequestFactory()
{
return statefullHttpComponentsClientHttpRequestFactory;
}
}
这里是一个类来表示一个REST客户端端,让你可以调用抵押和spring有个应用程序 安全性。
public class RestClient
{
private String host = "localhost";
private String port = "8080";
private String applicationPath;
private String apiPath = "api";
private String loginPath = "j_spring_security_check";
private String logoutPath = "logout";
private final String usernameInputFieldName = "j_username";
private final String passwordInputFieldName = "j_password";
private final StatefullRestTemplate template = new StatefullRestTemplate();
/**
* This method logs into a service by doing an standard http using the configuration in this class.
*
* @param username
* the username to log into the application with
* @param password
* the password to log into the application with
*
* @return the url that the login redirects to
*/
public String login(String username, String password)
{
MultiValueMap form = new LinkedMultiValueMap<>();
form.add(usernameInputFieldName, username);
form.add(passwordInputFieldName, password);
URI location = this.template.postForLocation(loginUrl(), form);
return location.toString();
}
/**
* Logout by doing an http get on the logout url
*
* @return result of the get as ResponseEntity
*/
public ResponseEntity logout()
{
return this.template.getForEntity(logoutUrl(), String.class);
}
public String applicationUrl(String relativePath)
{
return applicationUrl() + "/" + checkNotNull(relativePath);
}
public String apiUrl(String relativePath)
{
return applicationUrl(apiPath + "/" + checkNotNull(relativePath));
}
public StatefullRestTemplate template;
}
public String serverUrl()
{
return " CodeGo.net + host + ":" + port;
}
public String applicationUrl()
{
return serverUrl() + "/" + nullToEmpty(applicationPath);
}
public String loginUrl()
{
return applicationUrl(loginPath);
}
public String logoutUrl()
{
return applicationUrl(logoutPath);
}
public String apiUrl()
{
return applicationUrl(apiPath);
}
public void setLogoutPath(String logoutPath)
{
this.logoutPath = logoutPath;
}
public String getHost()
{
return host;
}
public void setHost(String host)
{
this.host = host;
}
public String getPort()
{
return port;
}
public void setPort(String port)
{
this.port = port;
}
public String getApplicationPath()
{
return applicationPath;
}
public void setApplicationPath(String contextPath)
{
this.applicationPath = contextPath;
}
public String getApiPath()
{
return apiPath;
}
public void setApiPath(String apiPath)
{
this.apiPath = apiPath;
}
public String getLoginPath()
{
return loginPath;
}
public void setLoginPath(String loginPath)
{
this.loginPath = loginPath;
}
public String getLogoutPath()
{
return logoutPath;
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("RestClient [\n serverUrl()=");
builder.append(serverUrl());
builder.append(", \n applicationUrl()=");
builder.append(applicationUrl());
builder.append(", \n loginUrl()=");
builder.append(loginUrl());
builder.append(", \n logoutUrl()=");
builder.append(logoutUrl());
builder.append(", \n apiUrl()=");
builder.append(apiUrl());
builder.append("\n]");
return builder.toString();
}
}
3. 该RestTemplate是非常基本的和有限的 CodeGo.net,似乎没有成为一个简单的方法来做到这一点。最好的办法可能是在Web应用程序1消化基本身份REST服务。 话虽这么说,对于测试我能解决这个一个大劈。基本上,RestTemplate提交登录(j_spring_security_check),解析出JSESSIONID从请求头,然后提交,其余请求。下面的代码,但我怀疑它是为生产做好准备代码的最佳解决方案。
public final class RESTTest {
public static void main(String[] args) {
RestTemplate rest = new RestTemplate();
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslsession) {
return true;
}
});
// setting up a trust store with JCA is a whole other issue
// this assumes you can only log in via SSL
// you could turn that off, but not on a production site!
System.setProperty("javax.net.ssl.trustStore", "/path/to/cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "somepassword");
String jsessionid = REST Test").asJSON());
}
} 注意这个工作,你需要在JCA创建一个存储,以便在SSL连接实际上可以做。我不想让Spring Security的登录是通过纯HTTP的生产现场,因为这将是一个巨大的安全漏洞。
4. 当前凭据应该可以在Web应用程序上1Authentication
对象,这是通过访问SecurityContext
(例如,你可以通过调用检索SecurityContextHolder.getContext().getAuthentication()
)。 当您检索凭据,您将它们访问Web应用程序2。 您可以通过扩展它与decorator(如下所述)通“Authentiation”头与RestTemplateRestTemplate.exchange()
方法,如在本论坛发表的文章中描述。
5. 有一个简单的方法来做到这一点的情况下,你是谁在寻找一个简单的调用,而不是一个API
HttpClient client = new HttpClient();
client.getParams().setAuthenticationPreemptive(true);
Credentials defaultcreds = new UsernamePasswordCredentials("username", "password");
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(new CommonsClientHttpRequestFactory(client));
client.getState().setCredentials(AuthScope.ANY, defaultcreds);
本文标题 :使用RestTemplate Spring安全认证
本文地址 :CodeGo.net/238843/
1. 在C ++坏分配异常 2. 其中这些存储方法是最快的? 3. VSS到SVN-库 我们终于从Visual Source S 4. 我怎样才能确保嵌套事务相互独立的承诺? 5. 使用URL路由时,asp.net多的Page_Load事件的用户控件 6. 如何显示使用servlet和JSP的PDF文件? [关闭] 7. 如何张贴到墙上的朋友使用Facebook的图形API为iPhone 8. jQuery的添加的iFrame与内容 9. 如何阅读收到的邮件使用C# 10. 十六进制转换在awk中为十进制或sed的 |