两个应用程序之间共享SPRING_SECURITY_CONTEXT(Share SPRING_SEC

2019-10-31 05:38发布

我有一个关于不同的端口(8080,8081)和不同CONFIGS(application.yml)本地主机运行两个不同的春季启动应用程序。 这些应用程序使用SSO使用OAuth 2.0,从授权服务器获得授权令牌。 我登录到我的第一个应用程序,获得授权和一切的伟大工程在这里。 现在我需要分享第二春启动应用程序(在端口8081),这些认证信息授权的授权服务器第二应用程序。 用Google搜索,发现2个aproaches:我可以尝试共享HttpSession两个应用程序之间(但我认为这是多余的)或HttpSessionSecurityContextRepositorySecurityContextRepository这似乎更方便。 这里的问题是,我无法管理这样做,我真不知道,这是一个好主意,分享2个应用程序之间的安全上下文。

我尝试了现在:

  1. 从通过在GET请求(定制按为授权服务器请求规范)头第一应用程序分享授权令牌,但它没有工作-第二次的应用程序不考虑采取这种令牌。
  2. 分享从第一个应用程序授权cookie来第二次,但它并不能工作。

我无法通过授权服务器上做第二应用程序的授权,因为它可能不是一个春天启动应用程序与@Controller但任何其他应用,而无需 HTML表单,所以我需要授权的第一应用(与UI),让所有的数据,需要进行授权的请求,并将它传递给第二应用(第三,第四......),所以他们能够做授权的请求了。

提前致谢!

Answer 1:

我相信,你的授权/资源服务器是外部application.And你可以用你的第一个应用程序,以便流是working.You有自己的CLIENT_ID,client_secret两个客户端应用程序等parameters.If这些参数是不同的,那么授权/资源成功登录application.Otherwise你需要在授权/资源服务器授权他们两个服务器将返回第一和第二客户不同bareer令牌会话ID的Cookie。 当用户进行登陆到第一个应用程序,然后在后台你也登录了第二个应用程序,我会提供。 对于自动授权第二个应用程序,你可以尝试做手工的oauth2登录流程的第二个应用程序与自己的参数时,首次成功应用登录后发送cookie来的前端,你从的oauth2登录了。

对于手动的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 oauthCookie = oauth2Login(authenticationRequest.getUsername(), authenticationRequest.getPassword(),
            CLIENT_ID, CLIENT_SECRET);

让饼干后,您需要更改其名称(例如JSESSIONID-秒),因为同样的Cookie将覆盖对方,还需要其领域路径更改为第二个应用程序域。

response.addCookie(oauthCookie);

最后你需要添加cookie来响应(这是HttpServletResponse参考)。

希望能帮助到你!



文章来源: Share SPRING_SECURITY_CONTEXT between two applications