簡體   English   中英

春季安全性OAuth2-對oauth / token的POST請求重定向到登錄名和角色顯示ROLE_ANONYMOUS

[英]Spring Security OAuth2- POST request to oauth/token redirects to login and role displays ROLE_ANONYMOUS

我正在跟蹤鏈接https://spring.io/blog/2015/02/03/sso-with-oauth2-angular-js-and-spring-security-part-v和github項目https:// github。 com / spring-guides / tut-spring-security-and-angular-js / tree / master / oauth2 我能夠登錄到OAuth提供程序,並在客戶端中重新獲得授權代碼。

現在,我從客戶端發出以下調用,以從提供程序獲取令牌(提供程序位於端口9999上)

        HttpHeaders headers = new HttpHeaders();
        headers.add("Accept",MediaType.APPLICATION_JSON_VALUE);
        List<String> cookies = httpEntity.getHeaders().get("Cookie");
        headers.put("Cookie", cookies);
        String redirectURL= "http://localhost:9999/oauthprovider/oauth/token" +  "?" + "response_type=token" + "&" + "grant_type=authorization_code" + "&" + "client_id=acme"+ "&" + "client_secret=acmesecret"+  "&" + "redirect_uri=http://localhost:8081/callback"+"&" + "code=" + authCode + "&" + "state=" + stateValue;

        HttpEntity<String> redirectResponse = template.exchange(
                redirectURL,
                    HttpMethod.POST,
                    responseentity,
                    String.class);


        result=redirectResponse.toString()

結果變量值具有以下內容(盡管不建議使用,但我已禁用了csrf並已將client_secret作為查詢參數發送(暫時))

    <302 Found,{X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Pragma=[no-cache], Expires=[0], X-Frame-Options=[DENY], Location=[http://localhost:9999/oauthprovider/oauthlogin], Content-Length=[0], Date=[Thu, 09 Nov 2017 12:07:37 GMT]}>

在控制台中,我有這些

   Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 2B669DF59BCE8047849BFBCA148BEE67; Granted Authorities: ROLE_ANONYMOUS

由於角色是ROLE_ANONYMOUS,我是否要重定向回登錄(如上所述,我正在日志中獲取登錄名)? 我該如何解決該問題?

添加有關代碼的更多詳細信息(僅對鏈接中提供的示例代碼進行了少量更改)。 提供者的上下文路徑為/ oauthprovider,通過curl調用,我得到了令牌。

@Configuration
@EnableAuthorizationServer
protected static class OAuth2AuthorizationConfig extends
        AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    //................................
    //................................
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("acme")
                .secret("acmesecret")
                .authorizedGrantTypes("authorization_code", "refresh_token",
                        "password").scopes("openid").autoApprove(true).redirectUris("http://localhost:8081/callback"); 
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception {
        endpoints.authenticationManager(authenticationManager).accessTokenConverter(
                jwtAccessTokenConverter());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer)
            throws Exception {
        oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess(
                "isAuthenticated()");
    }

}
@Configuration
@Order(-20)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
            .formLogin().loginPage("/oauthlogin").loginProcessingUrl("/login").failureUrl("/login?error=true").permitAll() 
        .and()
            .requestMatchers().antMatchers("/login", "/oauthlogin", "/oauth/authorize", "/oauth/token" ,"/oauth/confirm_access")
        .and()
            .authorizeRequests().anyRequest().authenticated();
        // @formatter:on

        http.csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.parentAuthenticationManager(authenticationManager);
    }
}

調用令牌端點你需要發送的Authorization標頭值base64(client_id:client_secret)和身體,你應該發送usernamepasswordgrant_typeFORM_URLENCODED

      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);
        // params
        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_TOKEN_URL.replace(OAUTH_HOST, oauthHost), request,
                    OauthTokenRespone.class);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

}

    @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
}

我最后一天的測試出了點問題。 如果我的處理程序在客戶端或提供程序中,我可以獲取訪問令牌。 如果我的重定向處理程序在提供程序中,則根據調試日志,用戶不是匿名的(可能是由於會話..?),但看起來我必須始終使用一個redirect_url。(否則,我會收到redirect_uri不匹配錯誤。)

以下是獲得json響應的工作代碼。

@ResponseBody
@RequestMapping(value = "/clientcallback", method = RequestMethod.GET)
public ResponseEntity<OauthTokenResponse> redirectCallback(@RequestParam (value= "code", defaultValue="") String authCode,@RequestParam (value= "state", defaultValue="") String stateValue,HttpEntity<String> httpEntity) 
{

    HttpHeaders headers = new HttpHeaders();
    RestTemplate restTemplate = new RestTemplate();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
    String plainCreds = "acme:acmesecret";
    byte[] plainCredsBytes = plainCreds.getBytes();
    byte[] base64CredsBytes = org.apache.commons.net.util.Base64.encodeBase64(plainCredsBytes);
    String base64Creds = new String(base64CredsBytes);
    headers.add("Authorization", "Basic " + base64Creds);

        List<String> cookies = httpEntity.getHeaders().get("Cookie");
        if(cookies != null)
        {
            headers.put("Cookie", cookies);
        }
        else
        {

            cookies = httpEntity.getHeaders().get("Set-Cookie");
            headers.put("Set-Cookie", cookies);
        }
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map,
                headers);

        OauthTokenResponse res = null;
        try {
            res = restTemplate.postForObject("http://localhost:9999/uaa/oauth/token?grant_type=authorization_code&client_id=acme&redirect_uri=http://localhost:8081/clientcallback&code=" + authCode, request,    
                    OauthTokenResponse.class);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return  new ResponseEntity<OauthTokenResponse>(res, HttpStatus.OK);
    }

再次感謝您的提示。

我知道這很舊,但是最近遇到了一個非常相似的問題,因此我發布了解決方案。

我以Simle SSO示例為基礎進行修改。 我正在使用映射到/ (web root)的spring安全過濾器和使用映射到/auth/*端點的spring oauth。 當我嘗試訪問/auth/oauth/token我將重定向到登錄頁面。 經過一些調試后,我找出了原因:

通過使用@EnableAuthorizationServer您將導入AuthorizationServerSecurityConfiguration ,該配置可保護端點/oauth/token/oauth/token_key/oauth/check_token 只要您的授權服務器映射到Web根目錄,一切都將使用此默認配置。 在我的情況下,對/auth/oauth/token請求只是重定向到登錄頁面,因為spring安全無法找到該路徑的規則。

我的解決方案是在我的spring安全配置中使用/auth前綴手動保護那些端點。

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM