oauth2 シングル サインオンを習得するのは難しいですか? 設定するだけです

シングル サインオンは、分散システムでは非常に一般的な要件です。

分散システムはさまざまなサブシステムで構成されており、システムを使用するときは一度ログインするだけで済むため、他のシステムはユーザーがすでにログインしていると認識し、再度ログインする必要はありません。Taobao Tmall、Alipay、Alibaba Cloud、その他の Web サイトにログインしてシングル サインオンを体験できます。

oauth2シングルサインオン機能に精通した劉備は、水を得た魚のように面会に行くと諸葛亮に会う。

今日、Heng 兄弟は、シングル サインオンのための Spring Boot+OAuth2 についてお話したいと思います。また、@EnableOAuth2Sso アノテーションを使用してシングル サインオン機能を迅速に実現します。
ソースコードのダウンロードアドレス

早速、手順を見ていきましょう

プロジェクトの作成

認可サーバーとリソースサーバーを一緒に構築します (もちろん、分離することが最善ですが、利便性を目的として一緒にされているエンタープライズ製品も多くあります)。

今日は合計 3 つのサービスが必要です。

プロジェクト ポートの説明
auth-server 9090 認可サーバー + リソース サーバー
client1 9091 サブシステム 1
client2 9092 サブシステム 2
auth-server は認可サーバー + リソース サーバーの役割を果たすために使用され、client1 と client2 はそれぞれサブシステムの役割を果たし、client1 は待機します。ログインが成功したら、client2 にアクセスして、シングル サインオンの効果を確認することもできます。

oauth2-sso という名前の Maven プロジェクトを親プロジェクトとして作成します。

統合認証センター

次に、統合認証センターを構築しましょう。

  • まず、auth-server というモジュールを作成し、作成時に次の依存関係を追加します。
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
  • プロジェクトが正常に作成された後、このモジュールは認可サーバー + リソース サーバーの役割を果たすことになるため、最初に @EnableResourceServer アノテーションをこのプロジェクトのスタートアップ クラスに追加して、これがリソース サーバーであることを示します。
@SpringBootApplication
@EnableResourceServer
public class AuthServerApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(AuthServerApplication.class, args);
    }

}
  • 次に、認可サーバーを構成します。リソース サーバーと認可サーバーがマージされるため、認可サーバーの構成がはるかに簡単になります。
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
    
    
    @Autowired
    PasswordEncoder passwordEncoder;

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

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    
    
        clients.inMemory()
                .withClient("api")
                .secret(passwordEncoder.encode("123456"))
                .autoApprove(true)
                .redirectUris("http://127.0.0.1:9091/login", "http://127.0.0.1:9092/login")
                .scopes("user")
                .accessTokenValiditySeconds(7200)
                .authorizedGrantTypes("authorization_code");

    }
}

ここではクライアント情報を設定するだけで済み、設定は非常に簡単です。

わかりやすくするために、クライアントの情報構成はメモリに基づいています。

  • 次に、Spring Security を再度構成しましょう。
@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    
    @Bean
    PasswordEncoder passwordEncoder() {
    
    
        return new BCryptPasswordEncoder();
    }
    @Override
    public void configure(WebSecurity web) throws Exception {
    
    
        web.ignoring().antMatchers("/login.html", "/css/**", "/js/**", "/images/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    
        http.requestMatchers()
                .antMatchers("/login")
                .antMatchers("/oauth/authorize")
                .and()
                .authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/login")
                .permitAll()
                .and()
                .csrf().disable();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
    
        auth.inMemoryAuthentication()
                .withUser("harry")
                .password(passwordEncoder().encode("admin123"))
                .roles("admin");
    }
}

大まかな概要は次のとおりです。

1. まず、パスワードの暗号化と復号化用の BCryptPasswordEncoder のインスタンスを提供します。
ログイン ページをカスタマイズしたため、これらの静的リソースは WebSecurity で許可されます。
HttpSecurityでは、認証関連のエンドポイントをリリースし、同時にログインページとログインインターフェースを設定します。
2. メモリベースのユーザーは AuthenticationManagerBuilder で提供されます (データベースからロードするようにここで変更できます)。
3. もう 1 つの重要なポイントがあります。リソース サーバーと認可サーバーが一緒にあるため、Spring Security 構成の優先順位を高めるために @Order アノテーションが必要です。

  • SecurityConfig と AuthServerConfig は両方とも認可サーバーが提供する必要があるものですが、認可サーバーとリソース サーバーを分割する場合は、ユーザー情報を公開するインターフェイスも提供する必要があります (認可サーバーとリソース サーバーが分離されている場合は、このインターフェースはリソースサーバーによって提供されます):
@RestController
public class UserController {
    
    
    @GetMapping("/user")
    public Principal getCurrentUser(Principal principal) {
    
    
        return principal;
    }
}
  • 最後に、application.properties でプロジェクト ポートを構成します。

server.port=9091
さらに、ヘン兄弟は次のようなログイン ページを事前に用意しました。

ここに画像の説明を挿入

  • ログイン ページに関連する html、css、js などを resource/static ディレクトリにコピーします。
    ここに画像の説明を挿入

  • このページは非常にシンプルで、ログイン フォームだけです。主要な部分をリストします。

<form action="/login" method="post">
    <div class="input">
        <label for="name">用户名</label>
        <input type="text" name="username" id="name">
        <span class="spin"></span>
    </div>
    <div class="input">
        <label for="pass">密码</label>
        <input type="password" name="password" id="pass">
        <span class="spin"></span>
    </div>
    <div class="button login">
        <button type="submit">
            <span>登录</span>
            <i class="fa fa-check"></i>
        </button>
    </div>
</form>

アクション送信アドレスは間違ってはいけません。

その後、統合認証ログイン プラットフォームは問題ありません。

クライアントの作成

次に、クライアント プロジェクトを作成しましょう。client1 という名前の Spring Boot プロジェクトを作成します。

  • 次の依存関係を追加します。
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>

  • プロジェクトが正常に作成されたら、Spring Security を構成しましょう。
@Configuration
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    
        http.authorizeRequests().anyRequest().authenticated().and().csrf().disable();
    }
}

この構成は非常に単純です。つまり、client1 のすべてのインターフェイスはアクセスする前に認証される必要があり、シングル サインオン機能を有効にするために @EnableOAuth2Sso アノテーションが追加されます。

  • 次に、client1 に別のテスト インターフェイスを提供します。
@RestController
public class UserController {
    
    
    @Value("${server.port}")
    private String port;
    @GetMapping("/getLogin")
    public String getLogin() {
    
    

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return "当前登录的用户是"+authentication.getName() + Arrays.toString(authentication.getAuthorities().toArray())+",登录端口:"+port;
    }
}

このテスト インターフェイスは、現在ログインしているユーザーの名前とロール情報、およびサービス ポート番号を返します。

  • 次に、client1 の application.properties で oauth2 関連情報を構成する必要があります。
security.oauth2.client.client-secret=123456
security.oauth2.client.client-id=api
security.oauth2.client.user-authorization-uri=http://127.0.0.1:9090/oauth/authorize
security.oauth2.client.access-token-uri=http://127.0.0.1:9090/oauth/token
security.oauth2.resource.user-info-uri=http://127.0.0.1:9090/user

server.port=9091

server.servlet.session.cookie.name=client1

ここの構成もよく知られているので、見てみましょう。

client-secret はクライアント シークレットです。
client-id はクライアント ID です。
user-authorization-uri は、ユーザー認証のエンドポイントです。
access-token-uri は、トークンを取得するためのエンドポイントです。
user-info-uri は、(リソースサーバーから取得した)ユーザー情報を取得するためのインターフェースです。
最後に、ポートを設定し、Cookie に名前を付けます。
その後、client1 の構成が完了します。

同様に、もう 1 つの client2 を設定してみましょう。Client2 は、Cookie の名前が異なることを除いて、client1 とまったく同じです (任意に選択できますが、異なる場合もあります)。

テスト

次に、auth-server、client1、client2 をそれぞれ起動します。まず、client1 の getLogin インターフェイスに移動します。このとき、自動的に統合認証センターにジャンプし、ユーザー名: harry、パスワード: admin123 を入力します

ログインに成功すると、次のように自動的に client1 の hello インターフェイスに戻ります。

ここに画像の説明を挿入

client1 がログインした後、再度 client2 にアクセスすると、ログインする必要がなく、直接アクセスできることがわかります。
ここに画像の説明を挿入

OK、その後、シングル サインオンは成功しました。

プロセス分析

最後に、上記のコードの実行プロセスを友達と一緒に見てみましょう。

1. まず、client1 の /getLogin インターフェイスにアクセスします。アクセスするにはログインが必要です。そのため、リクエストはインターセプトされます。インターセプト後、システムは client1 の /login インターフェイスにリダイレクトします。これにより、ログインに移動できるようになります。 。

ここに画像の説明を挿入

2. client1 のログイン インターフェイスにアクセスすると、@EnableOAuth2Sso アノテーションを設定しているため、この操作は再びインターセプトされ、シングル サインオン インターセプターは application.properties の設定に従って承認を取得するリクエストを自動的に開始します。コード:

ここに画像の説明を挿入

3. 2 番目のステップで送信されるリクエストは、auth-server サービス上で何かをリクエストするものですが、もちろん、このリクエストでは最初にログインする必要があるため、再度 auth-server のログイン ページにリダイレクトされます。中央に表示される統合認証です。
ここに画像の説明を挿入

4. 統合認証センターはログイン機能を完了した後、リクエストの 2 番目のステップの実行を継続し、この時点で認証コードを正常に取得できます。
ここに画像の説明を挿入
ここに画像の説明を挿入

5. 認証コードを取得すると、この時点では client1 のログイン ページにリダイレクトされますが、実際には client1 にはログイン ページがないため、この操作は引き続き傍受され、この時点で傍受されたアドレスはには認可コードが含まれているため、認可コードを取得し、OAuth2ClientAuthenticationProcessingFilter クラスで認証サーバーへのリクエストを開始すると、access_token を取得できます。
ここに画像の説明を挿入

6. 5番目の手順でaccess_tokenを取得した後、ログインユーザー情報を取得するために設定したuser-info-uriアドレスにリクエストを送信し、ユーザー情報を取得した後、client1で再度Spring Securityのログインプロセスを実行します。 。

プロジェクトについて学ぶ必要がある人は、私の github にアクセスして、
GitHub のソース コード アドレスを複製してください。

おすすめ

転載: blog.csdn.net/huangxuanheng/article/details/119052844