【11】統合認証ソリューション Spring Cloud OAuth2

Spring Cloud OAuth2 は、Spring Cloud システムの OAuth2 プロトコルの実装であり、複数のマイクロサービスの統合認証 (アイデンティティの正当性の検証) と認可 (アクセス許可の検証) に使用できます。特定のタイプのgrant_typeをOAuth2サービス(統合認証・認可サービス)に送信して一元的な認証・認可を行うことでaccess_token(アクセストークン)を取得し、このトークンが他のマイクロサービスから信頼されます。

  • セッションベースの認証方式

分散環境では、セッション ベースの認証によって問題が発生します。各アプリケーション サービスは
、ユーザー ID 情報をセッションに保存する必要があります。ロード バランシングを通じてローカル リクエストを別のアプリケーション サービスに分散するには
再認証されます。セッション共有やセッション貼り付けなどのソリューションを使用できます

  • トークンベースの認証方式

トークンベースの認証方式では、サーバーは認証データを保存する必要がなく、保守が容易で拡張性が高く、クライアントは任意の場所にトークンを保存でき、Webとアプリで統一された認証メカニズムを実装できます
欠点も明らかで、トークンには自己完結型の情報が含まれるため、
一般にデータ量が大きく、リクエストごとに送信する必要があるため、多くの帯域幅を消費します。さらに、トークン署名検証操作により、
CPU に追加の処理負荷がかかります。

OAuth2の概要

OAuth (Open Authorization) は、ユーザー名とパスワードをサードパーティ アプリケーションに提供したり、データのすべてのコンテンツを共有したりすることなく、サードパーティ アプリケーションが別のサービス プロバイダーに保存されている情報にアクセスすることを承認できるオープン プロトコル/標準です。

ここに画像の説明を挿入します

  • リソース所有者: ユーザー自身として理解できます
  • クライアント: Lagou.com など、ログインしたい Web サイトまたはアプリケーション
  • 認可サーバー: WeChat または QQ として理解できます。
  • リソース サーバー: WeChat または QQ として理解できます。

OAuth2のトークン認証方式

  • 認可コード
  • パスワードは、トークンと引き換えにユーザー名とパスワードを提供します。
  • 暗黙
  • クライアントの資格情報

認証サーバー(認可サーバー)を構築する

トークンの発行を担当する認可サーバー

  1. m-parent に基づいて新しいプロジェクト m-cloud-oauth-server-9999 を作成します。
    ここに画像の説明を挿入します
  2. pom.xml
        <!--导⼊Eureka Client依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--导⼊spring cloud oauth2依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.security.oauth.boot</groupId>
                    <artifactId>spring-security-oauth2-autoconfigure</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.1.11.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>
  1. application.yml (認証サーバーを構築します。設定ファイルには特別なものはありません)
server:
  port: 9999

spring:
  application:
    name: m-cloud-oauth-server

#注册发现
eureka:
  client:
    service-url:
      defaultZone: http://CloudEurekaServerA:8761/eureka,http://CloudEurekaServerB:8762/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${
    
    spring.cloud.client.ip-address}:${
    
    spring.application.name}:${
    
    server.port}:@project.version@

  1. スタートアップクラス
@SpringBootApplication
@EnableDiscoveryClient
@EnableAuthorizationServer //开启认证服务器功能
public class MCloudOuathServer9999 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(MCloudOuathServer9999.class, args);
    }

}
  1. 構成クラス
  • 認証サーバー構成クラス
package com.w.edu.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;


@Configuration
public class OauthServerConfiger extends AuthorizationServerConfigurerAdapter {
    
    
    @Autowired
    private AuthenticationManager authenticationManager;

    /**
     * 认证服务器最终以api接口方式对外提供服务(生成令牌、校验令牌)
     *
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    
    
        super.configure(security);
        security
                //允许客户端表单认证
                .allowFormAuthenticationForClients()
                //开启端口/oauth/token_key的访问权限
                .tokenKeyAccess("permitAll()")
                //开启端口/oauth/check_token的访问权限
                .checkTokenAccess("permitAll()");
    }

    /**
     * 客户端吧详情配置
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    
    
        super.configure(clients);
        //客户端信息存储在什么地方,既可以在内存也可以在数据库里
        clients.inMemory()
                //添加客户端配置。指定client_id
                .withClient("client_w")
                //指定客户端密码、安全码
                .secret("abcdef")
                //指定客户端可访问的资源id 清单
                .resourceIds("autodeliver")
                //认证类型、客户端令牌颁发模式//认证模式。可以配置多个
                .authorizedGrantTypes("password", "refresh_token")
                //客户端权限范围,配置all 即可
                .scopes("all");

    }

    /**
     * Token 令牌管理相关
     *
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    
    
        super.configure(endpoints);
        endpoints
                //token 存储方式
                .tokenStore(tokenStore())
                //配置token细节
                .tokenServices(authorizationServerTokenServices())
                //认证管理器
                .authenticationManager(authenticationManager)
                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
    }

    /**
     * Token 存储方式
     *
     * @return
     */
    public TokenStore tokenStore() {
    
    
        return new InMemoryTokenStore();
    }

    /**
     * 获取Token服务对象,描述token有效期等信息
     *
     * @return
     */
    public AuthorizationServerTokenServices authorizationServerTokenServices() {
    
    
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        //开启令牌刷新
        defaultTokenServices.setSupportRefreshToken(Boolean.TRUE);
        //
        defaultTokenServices.setTokenStore(tokenStore());
        //设置令牌有效时间(一半2小时)
        defaultTokenServices.setAccessTokenValiditySeconds(20);
        //设置令牌的有效时间
        defaultTokenServices.setRefreshTokenValiditySeconds(259200);
        return defaultTokenServices;
    }
}

  • セキュリティ構成クラス
package com.w.edu.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.ArrayList;

/**
 * @author Mrwg
 * @date 2023/4/13 20:30
 * @description
 * 处理用户名和密码的校验
 */
@Configuration
public class SecurityConfiger extends WebSecurityConfigurerAdapter {
    
    
    /**
     *注入AuthenticationManager
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
    
    
        return super.authenticationManagerBean();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
    
    
        return NoOpPasswordEncoder.getInstance();
    }

    /**
     * 处理用户名密码事宜
     * 1 客户传递username 和password 参数到认证服务器
     * 2一半存储在数据表中
     * 3 根据用户传递的数据,验证当前传递过来用户信息的合法性
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
    
       // 实例化用户对象
        UserDetails user = new User("admin","123456",new ArrayList<>());
        auth.inMemoryAuthentication()
                .withUser(user).passwordEncoder( passwordEncoder());
    }
}

  1. テスト

ここに画像の説明を挿入します

リソースサーバーの構築(リソースサーバー)

  1. リフォームm-service-autodeliver-8092サービスここに画像の説明を挿入します
  2. 依存関係
    認証サーバー OAuth2 依存関係をm-service-autodeliver-8092サービスに追加します
  3. application.yml
    の新しい構成
oauth2:
  server:
    check-token-url: http://localhost:9999/check_token
  1. テストコントローラーの追加
@RestController
@RequestMapping("/demo")
public class DemoController {
    
    


    /**
     * 使用Feign
     *
     * @param userId
     * @return
     */
    @GetMapping("/test")
    public String findResumeOpenState() {
    
    

        return "demo/test";
    }
}
@RestController
@RequestMapping("/other")
public class OtherController {
    
    


    /**
     * 使用Feign
     *
     * @param userId
     * @return
     */
    @GetMapping("/test")
    public String findResumeOpenState() {
    
    

        return "other/test";
    }
}
  1. サービスを開始して確認する
    ここに画像の説明を挿入します
  • 認証は必要ですが、インターフェイスにアクセスするための許可は必要ありません。
    ここに画像の説明を挿入します
    ここに画像の説明を挿入します
  • 認証やインターフェースへのアクセス許可は必要ありません
    ここに画像の説明を挿入します
  • トークンによるアクセス
    1. トークンの取得
      ここに画像の説明を挿入します
    2. アクセスインターフェース
      ここに画像の説明を挿入します

ここに画像の説明を挿入します

考える

考え方: 初めてログインするときに、認証サーバーはトークンを発行して認証サーバーに保存します。その後、リソースサーバーにアクセスするときにトークンを持ち歩きます。リソースサーバーは認証サーバーに検証を要求します。トークンの有効性. リソース サーバーが多数ある場合、認証サーバーは大きな負荷を受けることになります...

変換には JWT を使用します。JWT メカニズムを使用すると、リソース サーバーは認証サーバーにアクセスする必要がなくなります。

おすすめ

転載: blog.csdn.net/u014535922/article/details/130152538