使用RestTemplate Spring安全认证

53 篇文章 1 订阅

使用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. 我当时的情况。这里有我的解决方案。 服务器-春季安全配置
<sec:http>
 <sec:intercept-url pattern="/**" access="ROLE_USER" method="POST"/>
 <sec:intercept-url pattern="/**" filters="none" method="GET"/>
 <sec:http-basic />
</sec:http>
<sec:authentication-manager alias="authenticationManager">
 <sec:authentication-provider>
  <sec:user-service>
   <sec:user name="${rest.username}" password="${rest.password}" authorities="ROLE_USER"/>
  </sec:user-service>
 </sec:authentication-provider>
</sec:authentication-manager>
客户端端RestTemplate配置
<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
 <constructor-arg ref="httpClientParams"/>
 <property name="state" ref="httpState"/>
</bean>
<bean id="httpState" class="CustomHttpState">
 <property name="credentials" ref="credentials"/>
</bean>
<bean id="credentials" class="org.apache.commons.httpclient.UsernamePasswordCredentials">
 <constructor-arg value="${rest.username}"/>
 <constructor-arg value="${rest.password}"/>
</bean>
<bean id="httpClientFactory" class="org.springframework.http.client.CommonsClientHttpRequestFactory">
 <constructor-arg ref="httpClient"/>
</bean>

<bean class="org.springframework.web.client.RestTemplate">
 <constructor-arg ref="httpClientFactory"/>    
</bean>
自定义的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的依赖
<dependency>
 <groupId>commons-httpclient</groupId>
 <artifactId>commons-httpclient</artifactId>
 <version>3.1</version>
</dependency>

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<String, String> 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<String> 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()
 {
  return 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消化基本身份 验证的。 Apache的HttpClient的直接从Web应用程序2访问 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.execute(" CodeGo.net  HttpMethod.POST,
   new RequestCallback() {
    @Override
    public void doWithRequest(ClientHttpRequest request) throws IOException {
     request.getBody().write("j_username=user&j_password=user".getBytes());
    }
   }, new ResponseExtractor<String>() {
    @Override
    public String extractData(ClientHttpResponse response) throws IOException {
     List<String> cookies = response.getHeaders().get("Cookie");
     // assuming only one cookie with jsessionid as the only value
     if (cookies == null) {
      cookies = response.getHeaders().get("Set-Cookie");
     }
     String cookie = cookies.get(cookies.size() - 1);
     int start = cookie.indexOf('=');
     int end = cookie.indexOf(';');
     return cookie.substring(start + 1, end);
    }
   });
 rest.put(" CodeGo.net  + jsessionid, new DAO("REST Test").asJSON());
}
} 注意这个工作,你需要在JCA创建一个存储,以便在SSL连接实际上可以做。我不想让Spring Security的登录是通过纯HTTP的生产现场,因为这将是一个巨大的安全漏洞。
4. 当前凭据应该可以在Web应用程序上1 Authentication对象,这是通过访问 SecurityContext(例如,你可以通过调用检索 SecurityContextHolder.getContext().getAuthentication())。 当您检索凭据,您将它们访问Web应用程序2。 您可以通过扩展它与decorator(如下所述)通“Authentiation”头与RestTemplate RestTemplate.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的

 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值