java - 将非 Web 客户端的用户名和密码传递给 RestController Service 并在 Service 中检索
问题描述
部署在 Internet 上的遗留 Java 应用程序正在尝试与基于 Spring Security 的应用程序和 Intranet 上的 AuthenticationService 通信。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 代码。这里, String 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 Basic 或 Digest Authentication。我想了解从非基于 Web 的应用程序向服务发送和检索用户名/密码的方法。就像 login 应该是一个 POST 方法,用户名和密码作为 queryparam 或 pathparam 等传递
解决方案
好的,这里发生了几件事。
- 如果您的 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)。
- 假设您不希望 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
您的凭据并点击刷新几次
推荐阅读
- r - ggplot中的热图,每组不同的颜色
- javascript - 通过 PHP 调用外部文件中定义的 Javascript 函数
- dl4j - 解决 DL4J 编译错误
- swift - 查询Realm中的字符串列表
- javascript - 如果页面等于 X 并且购物车项目数等于 Y,则在 Woocommerce 上运行 Javascript
- c# - Active Directory:如何确定帐户是否为服务帐户?
- java - java 10 httpclient孵化器GET请求在node.js服务器上失败
- python - 如何在数组中附加下一个字典
- r - 如何:通过 RStudio 新订单 Binance API
- python - python迁移中的错误