从零开始 Spring Security OAuth2

文章也同步发表在我的个人博客:https://www.kangpeiqin.cn/#/index
欢迎关注我的个人博客与我交流。

前言

Spring Security OAuth 2.0 是 OAuth 2.0 协议的 Java 实现。这篇章主要是记录如何基于 Spring Security OAuth 2.0 搭建授权服务器和资源服务器。

概述

OAuth 2.0 是一个授权协议,可以用于以下的一些场景:

1、使用授权码模式向第三方系统授权,授予有限的访问权限。A 系统想获取 B 系统的用户信息,B 不需要提供用户名、密码给 A 系统(如果直接将密码给 A,A 就会拥有所有的权限,不太合适),而是经过用户授权提供令牌给 A,A 通过令牌获得 B 系统有限得访问权限。
2、使用密码模式,向信任的第一方系统进行授权。

前期准备

主要使用的包如下:

   	<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-security</artifactId>
        </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.0.9.RELEASE</version>
        </dependency>

授权服务器的配置

我们可以继承 AuthorizationServerConfigurerAdapter 并重写其中的方法来实现一些我们想要的功能,如:定义如何获取客户端信息等。

@Configuration
@EnableAuthorizationServer
@RequiredArgsConstructor
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    private final SysClientDetailsService sysClientDetailsService;

    private final SysUserService sysUserService;

    private final AuthenticationManager authenticationManager;

    private final TokenStore tokenStore;

    /**
     * 安全策略配置
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                // 获取 token key 需要进行 basic 认证客户端信息
                .tokenKeyAccess("isAuthenticated()")
                // 获取 token 信息同样需要 basic 认证客户端信息
                .checkTokenAccess("isAuthenticated()");
    }

    /**
     * 配置如何读取客户端信息:从数据库当中读取
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(sysClientDetailsService);
    }

    /**
     * 认证端点的配置,如:配置token的获取方式配置(从数据库当中获取、内存中获取、缓存中获取...)
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(sysUserService)
                .tokenStore(tokenStore);
    }

}

使用 @EnableAuthorizationServer 注解后,系统为我们配置了以下端点(Endpoint):

  • AuthorizationEndpoint:授权:/oauth/authorize
  • TokenEndpoint:获取令牌:/oauth/token
  • CheckTokenEndpoint:令牌校验:/oauth/check_token
  • WhitelabelErrorEndpoint: 授权失败:/oauth/error

资源服务器的配置

资源服务器和授权服务器可以是单独的一个应用,也可以是分开的。

@Configuration
@EnableResourceServer
@AllArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    private final ResourceServerProperties resourceServerProperties;
    private final TokenStore tokenStore;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.tokenStore(tokenStore)
                .resourceId(resourceServerProperties.getResourceId());
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        // 前后端分离下,可以关闭 csrf
        http.csrf().disable();
    }
}

在 application.yml 文件中配置授权服务器的相关信息

security:
  oauth2:
    resource:
      token-info-uri: http://127.0.0.1:8080/oauth/check_token
      id: test  # 资源id,可能存在多个资源服务器,可以配置客户端拥有哪些资源的访问权限
    client:  #资源服务器作为客户向授权服务器申请令牌
      client-id: test
      client-secret: oauth2
      access-token-uri: http://localhost:8080/oauth/token
      scope: READ,WRITE

示例

密码模式

  • 获取令牌
curl --location --request POST 'http://127.0.0.1:8080/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic b2F1dGgyOm9hdXRoMg==' \
--data-urlencode 'password=123456' \
--data-urlencode 'username=test' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'scope=READ WRITE'

  • 通过令牌访问需要权限的接口
curl --location --request GET 'http://127.0.0.1:8081/read' \
--header 'Authorization: bearer 2ea0da70-cfb3-44a8-8487-4fdebd5d9993'

授权码模式

  • 获取授权码
http://127.0.0.1:8080/oauth/authorize?response_type=code&client_id=example&redirect_uri=http://example.com&scope=READ

  • 根据授权码获取令牌
curl --location --request POST 'http://127.0.0.1:8080/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic ZXhhbXBsZTpvYXV0aDI=' \
--data-urlencode 'grant_type=authorization_code' \
--data-urlencode 'code=nW4iqR' \
--data-urlencode 'redirect_uri=http://example.com' \
--data-urlencode 'client_id=example' \
--data-urlencode 'scope=READ'

  • 刷新令牌
curl --location --request POST 'http://127.0.0.1:8080/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'Authorization: Basic ZXhhbXBsZTpvYXV0aDI=' \
--data-urlencode 'grant_type=refresh_token' \
--data-urlencode 'refresh_token=f9182c66-697a-4ea2-99a4-2b282617fca8'

最后

所涉及的代码可以点击这里

推荐的文章链接

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值