在两个应用程序之间共享SPRING\u安全性\u上下文
我有两个不同的Spring引导应用程序,它们运行在本地主机上的不同端口(808081)和不同配置(application.yml)上。这些应用程序使用SSO和OAuth 2.0从授权服务器获取授权令牌。我登录到我的第一个应用程序,获得授权,这里一切都很好。现在,我需要与第二个Spring Boot应用程序(在端口8081上)共享这些身份验证详细信息,以便在授权服务器中授权第二个应用程序。谷歌搜索发现了两个方法:我可以尝试在两个应用程序之间共享在两个应用程序之间共享SPRING\u安全性\u上下文,spring,rest,spring-mvc,single-sign-on,spring-security-oauth2,Spring,Rest,Spring Mvc,Single Sign On,Spring Security Oauth2,我有两个不同的Spring引导应用程序,它们运行在本地主机上的不同端口(808081)和不同配置(application.yml)上。这些应用程序使用SSO和OAuth 2.0从授权服务器获取授权令牌。我登录到我的第一个应用程序,获得授权,这里一切都很好。现在,我需要与第二个Spring Boot应用程序(在端口8081上)共享这些身份验证详细信息,以便在授权服务器中授权第二个应用程序。谷歌搜索发现了两个方法:我可以尝试在两个应用程序之间共享HttpSession(但我认为这是多余的),或者Ht
HttpSession
(但我认为这是多余的),或者HttpSessionSecurityContextRepository
作为securitycontentextrepository
,这似乎更方便。这里的问题是我无法做到这一点,我仍然不确定在两个应用程序之间共享安全上下文是否是一个好主意
我现在尝试的是:
@Controller
的Spring Boot应用程序,而是任何没有HTML表单的其他应用程序,所以我需要在第一个应用程序(带有UI)上进行授权,获取执行授权请求所需的所有数据并将其传递给第二个应用程序(第三,第四…)这样他们也可以进行授权请求
提前感谢!我假定您的授权/资源服务器是外部应用程序。您可以使用第一个应用程序成功登录,以便流程正常运行。您有两个客户端应用程序,具有自己的客户端id、客户端机密等参数。如果这些参数不同,则授权/资源服务器将返回di为第一个和第二个客户端应用程序提供不同的bareer令牌和sessionid cookie。否则,您需要在授权/资源服务器中对它们进行授权。 我会提供当用户登录到第一个应用程序,然后在后台你们也登录到第二个应用程序。 对于自动授权第二个应用程序,您可以尝试在第一个应用程序成功登录后,使用自己的参数手动执行第二个应用程序的oauth2登录流,并将从oauth2登录获得的cookie发送到前端 对于手动oauth2登录,您可以尝试以下代码:
private Cookie oauth2Login(String username, String password, String clientId, String clientSecret) {
try {
String oauthHost = InetAddress.getByName(OAUTH_HOST).getHostAddress();
HttpHeaders headers = new HttpHeaders();
RestTemplate restTemplate = new RestTemplate();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
// Basic Auth
String plainCreds = clientId + ":" + clientSecret;
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = org.apache.commons.net.util.Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
headers.add("Authorization", "Basic " + base64Creds);
// form param
map.add("username", username);
map.add("password", password);
map.add("grant_type", GRANT_TYPE);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map,
headers);
// CALLING TOKEN URL
OauthTokenRespone res = null;
try {
res = restTemplate.postForObject(OAUTH_HOST, request,
OauthTokenRespone.class);
} catch (Exception ex) {
ex.printStackTrace();
}
Optional<OauthTokenRespone> optRes = Optional.ofNullable(res);
String accessToken = optRes.orElseGet(() -> new OauthTokenRespone("", "", "", "", "", ""))
.getAccess_token();
// CALLING RESOURCE
headers.clear();
map.clear();
headers.setContentType(MediaType.APPLICATION_JSON);
map.add("access_token", accessToken);
request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
Cookie oauthCookie = null;
if (accessToken.length() > 0) {
HttpEntity<String> response = restTemplate.exchange(
OAUTH_RESOURCE_URL.replace(OAUTH_HOST, oauthHost) + "?access_token=" + accessToken,
HttpMethod.POST, request, String.class);
String cookie = Optional.ofNullable(response.getHeaders().get("Set-Cookie"))
.orElseGet(() -> Arrays.asList(new String(""))).get(0);
if (cookie.length() > 0) {
String[] c = cookie.split(";")[0].split("=");
oauthCookie = new Cookie(c[0], c[1]);
oauthCookie.setHttpOnly(true);
}
}
return Optional.ofNullable(oauthCookie).orElseGet(() -> new Cookie("Ops", ""));
} catch (Throwable t) {
return new Cookie("Ops", "");
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class OauthTokenRespone {
private String access_token;
private String token_type;
private String refresh_token;
private String expires_in;
private String scope;
private String organization;
// getter and setter
}
获取cookie后,您需要更改其名称(例如JSSessionID-SECOND),因为相同的cookie将相互覆盖,并且还需要将其域路径更改为第二个应用程序域
response.addCookie(oauthCookie);
最后,您需要将cookie添加到响应中(它是HttpServletResponse
reference)
希望有帮助!我假定您的授权/资源服务器是外部应用程序。您可以使用第一个应用程序成功登录,以便流程正常运行。您有两个客户端应用程序,具有自己的客户端id、客户端机密等参数。如果这些参数不同,则授权/资源服务器将返回不同的参数第一个和第二个客户端应用程序的ent bareer令牌和sessionid cookie。否则,您需要在授权/资源服务器中对它们进行授权。 我会提供当用户登录到第一个应用程序,然后在后台你们也登录到第二个应用程序。 对于自动授权第二个应用程序,您可以尝试在第一个应用程序成功登录后,使用自己的参数手动执行第二个应用程序的oauth2登录流,并将从oauth2登录获得的cookie发送到前端 对于手动oauth2登录,您可以尝试以下代码:
private Cookie oauth2Login(String username, String password, String clientId, String clientSecret) {
try {
String oauthHost = InetAddress.getByName(OAUTH_HOST).getHostAddress();
HttpHeaders headers = new HttpHeaders();
RestTemplate restTemplate = new RestTemplate();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
// Basic Auth
String plainCreds = clientId + ":" + clientSecret;
byte[] plainCredsBytes = plainCreds.getBytes();
byte[] base64CredsBytes = org.apache.commons.net.util.Base64.encodeBase64(plainCredsBytes);
String base64Creds = new String(base64CredsBytes);
headers.add("Authorization", "Basic " + base64Creds);
// form param
map.add("username", username);
map.add("password", password);
map.add("grant_type", GRANT_TYPE);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map,
headers);
// CALLING TOKEN URL
OauthTokenRespone res = null;
try {
res = restTemplate.postForObject(OAUTH_HOST, request,
OauthTokenRespone.class);
} catch (Exception ex) {
ex.printStackTrace();
}
Optional<OauthTokenRespone> optRes = Optional.ofNullable(res);
String accessToken = optRes.orElseGet(() -> new OauthTokenRespone("", "", "", "", "", ""))
.getAccess_token();
// CALLING RESOURCE
headers.clear();
map.clear();
headers.setContentType(MediaType.APPLICATION_JSON);
map.add("access_token", accessToken);
request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
Cookie oauthCookie = null;
if (accessToken.length() > 0) {
HttpEntity<String> response = restTemplate.exchange(
OAUTH_RESOURCE_URL.replace(OAUTH_HOST, oauthHost) + "?access_token=" + accessToken,
HttpMethod.POST, request, String.class);
String cookie = Optional.ofNullable(response.getHeaders().get("Set-Cookie"))
.orElseGet(() -> Arrays.asList(new String(""))).get(0);
if (cookie.length() > 0) {
String[] c = cookie.split(";")[0].split("=");
oauthCookie = new Cookie(c[0], c[1]);
oauthCookie.setHttpOnly(true);
}
}
return Optional.ofNullable(oauthCookie).orElseGet(() -> new Cookie("Ops", ""));
} catch (Throwable t) {
return new Cookie("Ops", "");
}
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class OauthTokenRespone {
private String access_token;
private String token_type;
private String refresh_token;
private String expires_in;
private String scope;
private String organization;
// getter and setter
}
获取cookie后,您需要更改其名称(例如JSSessionID-SECOND),因为相同的cookie将相互覆盖,并且还需要将其域路径更改为第二个应用程序域
response.addCookie(oauthCookie);
最后,您需要将cookie添加到响应中(它是HttpServletResponse
reference)
希望有帮助!您的授权/资源服务器是另一个应用程序。对吗?您是否请求相同的客户端id和客户端密码?是的,资源服务器是另一个应用程序。从第二个应用程序我请求不同的客户端id和客户端密码。当然,与第一个应用程序不同。您的授权/资源服务器是另一个应用程序。对吗?您是否请求相同的客户端id和客户端密码?是的,资源服务器是另一个应用程序。从第二个应用程序我请求不同的客户端id和客户端密码。当然,与第一个应用程序不同。感谢您的回复,但我们找到了另一个解决方案!在OAuth上下文中,我们有另一个实体,称为“资源服务器”。您可以通过从身份验证服务器获取的access_令牌访问它。因此,在第二个应用程序上,我添加了@EnableResourceServer注释,在标题中使用access_令牌发出了GET请求,并获得了我所需的信息。非常简单,非常遗憾,我花了两周时间找到了最佳解决方案。但再次感谢您的回复。我没有快速回答您的问题在bc上,我的工作真的很忙…\=谢谢你的回复,但我们找到了另一个解决方案!在OAuth上下文中,我们有另一个实体,称为“资源服务器”。您可以通过从身份验证服务器获取的access_令牌访问它。因此,在第二个应用程序上,我添加了@EnableResourceServer注释,在标题中使用access_令牌发出了GET请求,并获得了我所需的信息。非常简单,非常遗憾,我花了两周时间找到了最佳解决方案。但再次感谢您的回复。我没有快速回答您的问题公元前一年,我的工作真的很忙\=