将用户名和密码从非Web客户端传递到RestController服务并在服务中检索

时间:2019-01-08 16:05:13

标签: java rest spring-security apache-httpclient-4.x

部署在Internet上的旧版Java应用程序正试图与AuthenticationService通信,后者是基于Spring Security的应用程序和Intranet。发送用户名和密码后,AuthenticationService会对任何用户进行身份验证。客户端代码为:

    public static void ApacheHttpClient(String userID, String userPWD){
            CredentialsProvider provider = new BasicCredentialsProvider();
            UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(userID, userPWD);
            provider.setCredentials(AuthScope.ANY, credentials);

            HttpClient client = HttpClientBuilder.create()
              .setDefaultCredentialsProvider(provider)
              .build();
            String URL_SECURED_BY_BASIC_AUTHENTICATION = "http://localhost:8080/abc/login";
            try {

                HttpResponse response = client.execute(
                  new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION));
                int statusCode = response.getStatusLine()
                  .getStatusCode();
              System.out.println("Response Status Code : "+statusCode);
              HttpEntity entity = response.getEntity();
} catch (Exception e) {
          e.printStackTrace();
        } finally {
            client.getConnectionManager().shutdown();
        }

用于接受用户名和密码并进行身份验证的AuthenticationService代码。在这里,字符串auth = request.getHeader(“ Authorization”);总是为空

@RestController
@RequestMapping("/abc")
public class Authenticate {

     @Autowired
        private LoginService loginService;

    @RequestMapping("/login")
    public void login(HttpServletRequest request, HttpServletResponse response) {
        try {
            String auth = request.getHeader("Authorization");
            if(auth != null && auth.length() > 6){
                String userpassEncoded = auth.substring(6);  
                // Decode it, using any base 64 decoder  
                sun.misc.BASE64Decoder dec = new sun.misc.BASE64Decoder();  
                String userpassDecoded= new String(dec.decodeBuffer(userpassEncoded));
                System.out.println(" userpassDecoded = "+userpassDecoded);
             }
           } catch (Exception e) {
            e.printStackTrace();
           }

           }

通常,建议使用HTTP基本或摘要身份验证。我想了解从非基于Web的应用程序向服务发送和检索用户名/密码的方法。就像应该以POST方法登录,并以queryparam或pathparam等方式传递用户名和密码

1 个答案:

答案 0 :(得分:1)

好的,这里发生了几件事。

  1. 如果您的AuthenticationService正确设置,您的ApacheHttpClient将可以正常工作。 因此,假设您相信AuthenticationService使用Spring Security可以正常工作。 请执行:

curl -i http://localhost:8080/abc/login

您看到这样的回复吗?

HTTP/1.1 401 Unauthorized WWW-Authenticate: Basic realm="Spring Security Application"

如果没有看到WWW-Authenticate标头。然后,您的AuthorizationService未设置为处理基本身份验证。您没有配置Spring Security为您执行基本身份验证。

您会看到,为基本身份验证设置的应用程序应使用401响应和标头自动挑战客户端(例如浏览器或HttpClient)。

  1. 让我们假设您不希望Spring Security保护您的端点。

在这种情况下,您可以将HttpClient配置为始终根据请求发送Authorization头(而不是像1中所描述的那样等待挑战)

代码看起来像这样:

public static String ApacheHttpClient(String userID,
                                    String userPWD,
                                    String url,
                                    boolean preempt) throws Exception {
    CredentialsProvider provider = new BasicCredentialsProvider();
    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(userID, userPWD);
    provider.setCredentials(AuthScope.ANY, credentials);
    HttpClientContext context = HttpClientContext.create();

    HttpClientBuilder builder = HttpClientBuilder.create();
    if (preempt) {
        AuthCache authCache = new BasicAuthCache();
        authCache.put(HttpHost.create(url), new BasicScheme());
        context.setCredentialsProvider(provider);
        context.setAuthCache(authCache);
    } else {
        builder.setDefaultCredentialsProvider(provider);
    }
    HttpClient client = builder.build();
    try {
        HttpResponse response = client.execute(new HttpGet(url), context);
        int statusCode = response.getStatusLine().getStatusCode();
        System.out.println("Response Status Code : " + statusCode);
        return EntityUtils.toString(response.getEntity());
    } finally {
        client.getConnectionManager().shutdown();
    }
}

我为您创建了一些示例供您试用

git clone https://github.com/fhanik/spring-security-community.git
cd spring-security-community
./gradlew :spring-security-community-samples-basic-authentication-client:bootRun

首先访问非安全页面:http://localhost:8080/non-secure

然后访问安全页面:http://localhost:8080/secure

输入user/password作为您的凭据,然后点击几次刷新

我还为您的client和如何test it添加了代码