1. 程式人生 > >Spring Security Oauth2系列(七)

Spring Security Oauth2系列(七)

摘要:

今天來給大家分享一下期待已久的oauth2回撥地址的設定,相信接觸過oauth2的很多coder已經按捺不住激動的心情了吧。因為這個回撥地址的配置能夠讓授權碼模式的運用的主動權掌握在自己的手中,可以根據自己的不同專案的實際情況設定不同的回撥,例如社群的GitHub的示例:Spring Cloud Security系列教程一:入門

DefaultRedirectResolver

首先分析一下org.springframework.security.oauth2.provider.endpoint.DefaultRedirectResolver原始碼:

 public String resolveRedirect
(String requestedRedirect, ClientDetails client) throws OAuth2Exception
{ Set<String> authorizedGrantTypes = client.getAuthorizedGrantTypes(); if (authorizedGrantTypes.isEmpty()) { throw new InvalidGrantException("A client must have at least one authorized grant type."
); } else if (!this.containsRedirectGrantType(authorizedGrantTypes)) { throw new InvalidGrantException("A redirect_uri can only be used by implicit or authorization_code grant types."); } else { Set<String> redirectUris = client.getRegisteredRedirectUri(); if
(redirectUris != null && !redirectUris.isEmpty()) { return this.obtainMatchingRedirect(redirectUris, requestedRedirect); } else if (StringUtils.hasText(requestedRedirect)) { return requestedRedirect; } else { throw new InvalidRequestException("A redirect_uri must be supplied."); } } }

對重定向路徑進行解析,如果不進行設定預設就是當前路徑,這裡指的當前路徑是指:比如當你在訪問security進行了許可權控制的路徑http://localhost:8080/client時候,跳轉到oauth2的登陸首頁,此時當前頁面指的就是http://localhost:8080/client

 private String obtainMatchingRedirect(Set<String> redirectUris, String requestedRedirect) {
        Assert.notEmpty(redirectUris, "Redirect URIs cannot be empty");
        if (redirectUris.size() == 1 && requestedRedirect == null) {
            return (String)redirectUris.iterator().next();
        } else {
            Iterator var3 = redirectUris.iterator();

            String redirectUri;
            do {
                if (!var3.hasNext()) {
                    throw new RedirectMismatchException("Invalid redirect: " + requestedRedirect + " does not match one of the registered values: " + redirectUris.toString());
                }

                redirectUri = (String)var3.next();
            } while(requestedRedirect == null || !this.redirectMatches(requestedRedirect, redirectUri));

            return requestedRedirect;
        }
    }

這個方法是來判斷客戶端的設定回撥地址是否和服務端的回撥地址一致

AbstractRedirectResourceDetails

核心方法解析,AbstractRedirectResourceDetails是一個抽象類,位於
org.springframework.security.oauth2.client.token.grant.redirect.AbstractRedirectResourceDetails
一起來看原始碼吧

package org.springframework.security.oauth2.client.token.grant.redirect;

import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;

public abstract class AbstractRedirectResourceDetails extends BaseOAuth2ProtectedResourceDetails {
    private String preEstablishedRedirectUri;
    private String userAuthorizationUri;
    private boolean useCurrentUri = true;

    public AbstractRedirectResourceDetails() {
    }

    public void setUseCurrentUri(boolean useCurrentUri) {
        this.useCurrentUri = useCurrentUri;
    }

    public boolean isUseCurrentUri() {
        return this.useCurrentUri;
    }

    public String getUserAuthorizationUri() {
        return this.userAuthorizationUri;
    }

    public void setUserAuthorizationUri(String userAuthorizationUri) {
        this.userAuthorizationUri = userAuthorizationUri;
    }

    public String getPreEstablishedRedirectUri() {
        return this.preEstablishedRedirectUri;
    }

    public void setPreEstablishedRedirectUri(String preEstablishedRedirectUri) {
        //此處可以在客戶端進行自定義設定
        this.preEstablishedRedirectUri = preEstablishedRedirectUri;
    }

    public String getRedirectUri(AccessTokenRequest request) {
        String redirectUri = (String)request.getFirst("redirect_uri");
        if (redirectUri == null && request.getCurrentUri() != null && this.useCurrentUri) {
            redirectUri = request.getCurrentUri();
        }

        if (redirectUri == null && this.getPreEstablishedRedirectUri() != null) {
            redirectUri = this.getPreEstablishedRedirectUri();
        }
      //返回回撥地址
        return redirectUri;
    }
}

原始碼特別簡單,這裡不做過多的解釋,部分關鍵配置我給大家貼出來
我的閘道器服務配置如下:

security:
  oauth2:
    client:
      client-id: fbed1d1b4b1449daa4bc49397cbe2350
      client-secret: fbed1d1b4b1449daa4bc49397cbe2350
      access-token-uri: http://localhost:8088/oauth/token
      user-authorization-uri: http://localhost:8088/oauth/authorize
      scope: read,write
      pre-established-redirect-uri: http://localhost:8080/session
      use-current-uri: false//此處特別重要一定要配置,否則不會生效,配置了自定義的回撥地址就必須將預設的回撥禁止,原因不做過多說明。
    resource:
      user-info-uri: http://localhost:8088/user
      prefer-token-info: false

我的oauth2關鍵配置如下:

     @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        clients.inMemory()
                .withClient("fbed1d1b4b1449daa4bc49397cbe2350")
                .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
                .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
                .scopes("read","write")
                .secret("fbed1d1b4b1449daa4bc49397cbe2350")
                .accessTokenValiditySeconds(120)//Access token is only valid for 2 minutes.
                .refreshTokenValiditySeconds(600)//Refresh token is only valid for 10 minutes.
                .redirectUris("http://localhost:8080/session");

    }

總結:

該篇文章主要講了oauth2 的回撥地址,相信是大家期待已久的功能點了,由於工作上的原因,完成這個分析的主要功能還是我的一個朋友張順,有問題的大家繼續在評論上提出來,希望能夠在今後的專案實踐中將oauth2的優勢體現得淋漓盡致!
參考本人github地址:https://github.com/dqqzj/spring4all/tree/master/oauth2