ホームページ  >  記事  >  Java  >  SpringBootセキュリティ管理のOAuth2フレームワークの使用方法

SpringBootセキュリティ管理のOAuth2フレームワークの使用方法

WBOY
WBOY転載
2023-05-18 08:08:061279ブラウズ

OAuth3 の概要

OAuth は、Web サイトに保存されているユーザーのプライベート リソース (アバター、写真、ビデオなど) にサードパーティのアプリケーションがアクセスできるようにするオープン スタンダードです。プロセス中にサードパーティのアプリケーションにユーザー名とパスワードを提供する必要はありません。

特定のサービス プロバイダーに保存されているデータへのアクセスは、ユーザー名とパスワードの代わりにトークンを使用して実現されます。各トークンは、特定の Web サイトが特定の期間、特定のリソースにアクセスすることを許可します。

OAuth を使用すると、ユーザーはサードパーティの Web サイトが、すべての情報ではなく、他のリソース サーバーに保存されている特定の情報に柔軟にアクセスできるようになります。たとえば、ユーザーが QQ を通じて Zhihu にログインしたい場合、Zhihu はサードパーティ アプリケーションです。Zhihu がユーザーの基本情報にアクセスしたい場合は、ユーザーの承認が必要です。ユーザーが Zhihu に自分の QQ ユーザーを伝えた場合、名前とパスワードを指定すると、Zhihu はユーザーのすべてのデータにアクセスでき、ユーザーだけがパスワードを変更して権限を取り消すことができます。この認証方法には大きなセキュリティ上のリスクがあります。OAuth を使用すると、この問題はうまく解決できます。

トークンを使用すると、ユーザーはサードパーティ アプリケーションからのアクセス許可を柔軟に承認または取り消すことができます。 OAuth 2 は OAuth プロトコルの次のバージョンですが、OAuth 1.0 との下位互換性はありません。

OAuth 2 は、Web アプリケーション、デスクトップ アプリケーション、モバイル デバイス、リビング ルーム デバイスに特化した認証プロセスを提供しながら、クライアント開発者の簡素化に重点を置いています。従来の Web 開発のログイン認証は一般にセッションに基づいていますが、フロントエンドとバックエンドの分離されたアーキテクチャでセッションを使用し続けると、モバイル端末 (Android、IOS、WeChat アプレットなど) が認証を行わないため、多くの不便が生じます。 Cookie (WeChat アプレット) をサポートしていないと非常に不便ですが、OAuth 2 認証を使用することで解決できます。

OAuth3 の役割

まず、OAuth 2 のいくつかの基本的な役割を理解します。

  • リソース所有者: つまり、アバター、写真、ビデオなどを持つユーザーです。リソース

  • クライアント: つまり、サードパーティのアプリケーション

  • 認可サーバー: ユーザーが提供した情報が正しいかどうかを確認するために使用されます。修正してトークンを返す サードパーティ アプリケーションの場合

  • # リソース サーバー: アバター、写真、ビデオ、その他のリソースなどのユーザー リソースを提供するサーバー

一般に、認可サーバーとリソース サーバーは同じサーバーであってもかまいません。

OAuth3 認可プロセス

ステップ 01: クライアント (サードパーティ アプリケーション) がユーザーに認可を要求します。

ユーザーがサービス認可ページの「認可に同意する」ボタンをクリックすると、サーバーは認可証明書をクライアントに返します。

ステップ 03: クライアントは、トークンを申請するために認可ライセンスを認可サーバーに渡します。

ステップ 04: 認可サーバーは情報が正しいことを確認した後、クライアントにトークンを発行します。

ステップ 05: クライアントは、リソースにアクセスするためにトークンをリソース サーバーに受け取ります。

ステップ 06: リソース サーバーはトークンが正しいことを検証し、リソースを開きます。

認可モード

OAuthプロトコルの認可モードは以下の4種類に分かれています

  • #認可コード認可モードはその中で最も充実した機能です。このプロセスは最も厳格であり、認証コードが鍵となります。このモードの特徴は、クライアントサーバーが認可サーバーと対話することであり、国内の一般的なサードパーティプラットフォームのログイン機能は基本的にこの方式を採用しています

  • 簡易モード: 簡易モードは認証サーバーを必要としません。クライアント エンド サーバーが参加し、ブラウザ内の認可サーバーから直接トークンを申請します。通常、純粋に静的なページの場合、この方法を使用できます。

  • パスワード モードでは、ユーザーはクライアントに直接申請し、ユーザー名とパスワードを提供すると、クライアントはこの情報を使用して認可サーバーにアクセス トークンを要求します。ユーザーは、クライアント アプリケーションとサービス プロバイダーが同じ会社のものであるかどうかなど、クライアントに関する高レベルの情報を知る必要があります。

  • クライアント モードでは、サービス プロバイダーがクライアントを承認します。特定のユーザーよりも。厳密に言えば、クライアント モードは OAuth プロトコルが解決する問題の解決策とみなされませんが、開発者にとっては、一部のフロントエンドとバックエンドの分離アプリケーションや、提供されている認証および認可サーバーでこの方法を使用すると便利です。

  • #4 つのモードにはそれぞれメリットがあり、さまざまな開発シナリオに適しており、開発者は実際の状況に応じて選択できます

実践

ここで紹介するのは、フロントエンドとバックエンドの分離アプリケーション(またはモバイル端末やWeChatアプレットなど)向けに提供される認証サーバーにOAuthサービスを構築する方法です。モードを中心に紹介します。

1. プロジェクトを作成し、依存関係を追加します

Spring Boot Web プロジェクトを作成し、以下の依存関係を追加します

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
  <exclusions>
    <exclusion>
      <groupId>io.lettuce</groupId>
      <artifactId>lettuce-core</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.security.oauth</groupId>
  <artifactId>spring-security-oauth3</artifactId>
  <version>2.3.3.RELEASE</version>
</dependency>

Spring Boot の OAuth プロトコルは基本的に完成しているので、 Spring Security の依存関係を追加する必要があるので、まず Spring Security の依存関係を追加する必要がありますが、これには OAuth 2 が必要なので、OAuth 2 関連の依存関係を追加します トークンは Redis キャッシュ サーバーに保存できます 同時に、Redis には有効期限などの機能がありますトークンの保管に非常に適しているため、Redis も追加されています。

構成 application.properties

spring.redis.database=0
spring.redis.host=ip地址
spring.redis.port=6379
spring.redis.password=root
spring.redis.jedis.pool.max-active=8
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.max-wait=-1ms
spring.redis.jedis.pool.min-idle=0

2. 配置授权服务器

授权服务器和资源服务器可以是同一台服务器,也可以是不同服务器,此处假设是同一台服务器,通过不同的配置分别开启授权服务器和资源服务器,首先是授权服务器:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    RedisConnectionFactory redisConnectionFactory;
    @Autowired
    UserDetailsService userDetailsService;
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("password")
                .authorizedGrantTypes("password", "refresh_token")
                .accessTokenValiditySeconds(1800)
                .resourceIds("rid")
                .scopes("all")
                .secret("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq");
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService);
    }
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients();
    }
}

代码解释:

  • 自定义类继承自 AuthorizationServerConfigurerAdapter ,完成对授权服务器的配置,然后通过 @EnableAuthorizationServer 注解开启授权服务器

  • 注入 AuthenticationManager 用来支持 password 模式

  • 注入 RedisConnectionFactory 用来完成 Redis 缓存,将令牌信息储存到 Redis 缓存中

  • 注入 UserDetailsService 该对象为刷新 token 提供支持

  • 在 configure(ClientDetailsServiceConfigurer clients) 方法中配置 password 授权模式,authorizedGrantTypes 表示 OAuth 2 中的授权模式为 password 和 refresh_token 两种,在标准的 OAuth 2 协议中,授权模式并不包括 refresh_token ,但是在 Spring Security 的实现中将其归为一种,因此如果要实现 access_token 的刷新,就需要添加这样一种授权模式;accessTokenValiditySeconds 方法配置了 access_token 的过期时间;resourceIds 配置了资源 id;secret 方法配置了加密后的密码,明文是 123

  • configure(AuthorizationServerEndpointsConfigurer endpoints) 方法配置了令牌的存储,AuthenticationManager 和 UserDetailsService 主要用于支持 password 模式以及令牌的刷新

  • configure(AuthorizationServerSecurityConfigurer security) 方法配置表示支持 client_id 和 client_secret 做登录认证

3. 配置资源服务器

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("rid").stateless(true);
    }
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated();
    }
}

代码解释:

  • 自定义类继承自 ResourceServerConfigurerAdapter ,并添加 @EnableResourceServer 注解开启资源服务器配置

  • resources.resourceId(“rid”).stateless(true); 配置资源 id,这里的资源 id 和授权服务器中的资源 id 一直,然后设置这些资源仅基于令牌认证

  • configure(HttpSecurity http) 方法配置 HttpSecurity

4. 配置 Security

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        return super.userDetailsService();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                .roles("admin")
                .and()
                .withUser("sang")
                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                .roles("user");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/oauth/**").authorizeRequests()
                .antMatchers("/oauth/**").permitAll()
                .and().csrf().disable();
    }
}

这里两个 Bean 将注入授权服务器配置类中使用,另外,这里的 HttpSecurity 配置主要是配置 /oauth/** 模式的 URL ,这一类的请求直接放行。在 Spring Security 配置和资源服务器配置中,一共涉及两个 HttpSecurity ,其中 Spring Security 中的配置优先级高于资源服务器中的配置,即请求地址先经过 Spring Security 的 HttpSecurity ,再经过资源服务器的 HttpSecurity。

5. 验证测试

首先创建三个简单的请求地址

@RestController
public class HelloController {
    @GetMapping("/admin/hello")
    public String admin() {
        return "Hello admin!";
    }
    @GetMapping("/user/hello")
    public String user() {
        return "Hello user!";
    }
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }
}

根据前文的配置,要请求这三个地址,分别需要 admin 角色、user 角色以及登录后访问。

所有都配置完成后,启动 Redis 服务器,再启动 Spring Boot 项目,首先发送一个 POST 请求获取 token,请求地址如下(注意这里是一个 POST 请求,为了显示方便,将参数写在地址栏中):http://localhost:8080/oauth/token?username=sang&password=123&grant_type=password&client_id=password&scope=all&client_secret=123

请求地址中包含的参数有用户名、密码、授权模式、客户端 id 、scope 以及客户端密码,基本就是授权服务器中所配置的数据,请求结果如图

SpringBootセキュリティ管理のOAuth2フレームワークの使用方法

其中 access_token 是获取其它资源时要用的令牌,refresh_token 用来刷新令牌,expires_in 表示 access_token 过期时间,当 access_token 过期后,使用 refresh_token 重新获取新的 access_token (前提是 refresh_token 未过期),请求地址(注意也是POST请求):http://localhost:8080/oauth/token?grant_type=refresh_token&refresh_token=693b0e36-4515-442a-8c5d-90bade3c74d2&client_id=password&client_secret=123

获取新的 access_token 时需要携带上 refresh_token ,同事授权模式设置为 refresh_token ,在获取的结果中 access_token 会变化,同时 access_token 有效期也会变化,如图

SpringBootセキュリティ管理のOAuth2フレームワークの使用方法

接下来访问所有资源,携带上 access_token 参数即可,例如 /user/hello 接口:http://localhost:8080/user/hello?access_token=0497e4bc-df37-460e-8755-b813b9dbf36a,访问结果如图

SpringBootセキュリティ管理のOAuth2フレームワークの使用方法

#リソースが不正にアクセスされた場合、たとえば、sang ユーザーが /admin/hello インターフェイスにアクセスした場合、結果は図に示すとおりになります。

SpringBootセキュリティ管理のOAuth2フレームワークの使用方法

##この時点で、パスワード モード OAuth 認証システムが正常に確立されます。

OAuth には 4 つの認証モードがあり、開発者は開発の実情に応じていずれかを選択する必要がありますが、ここではフロントエンドとバックエンドを分離するアプリケーションで一般的に使用されるパスワード モードを紹介します。他の認証モードも同様であり、それぞれに独自の使用シナリオがあります。

全体として、Spring Security OAuth 2 の使用はまだ比較的複雑であり、設定も比較的面倒ですが、開発者のアプリケーション シナリオが比較的単純であれば、認可に従って独自の OAuth 2 認証システムを構築できます。ここで紹介するプロセスです。

以上がSpringBootセキュリティ管理のOAuth2フレームワークの使用方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。