配置OAuth2认证服务器和资源服务器-完整示例

2023-04-13 18:33:17 浏览数 (3)

1. 创建 Spring Boot 项目

首先,我们需要创建一个新的 Spring Boot 项目,并添加如下的依赖:

代码语言:javascript复制
phpCopy code<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
</dependency>

2. 配置 OAuth2 认证服务器

在 Spring Boot 项目的 application.yml 或 application.properties 文件中添加 OAuth2 认证服务器的配置:

代码语言:javascript复制
yamlCopy codesecurity:
  oauth2:
    client:
      clientId: clientapp
      clientSecret: secret
      authorizedGrantTypes: authorization_code,refresh_token,password
      scopes: openid,read,write
    authorization:
      tokenKeyAccess: hasAuthority('ROLE_TRUSTED_CLIENT')
      checkTokenAccess: hasAuthority('ROLE_TRUSTED_CLIENT')

3. 创建授权服务器

创建一个授权服务器类,继承 AuthorizationServerConfigurerAdapter 类,实现其中的 configure() 方法。

代码语言:javascript复制
javaCopy code@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .inMemory()
                .withClient("clientapp")
                .secret("{noop}secret")
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("openid", "read", "write")
                .accessTokenValiditySeconds(120)
                .refreshTokenValiditySeconds(600);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .authenticationManager(authenticationManager)
                .tokenStore(tokenStore())
                .accessTokenConverter(accessTokenConverter());
    }

    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("123456");
        return converter;
    }
}

4. 创建资源服务器

创建一个资源服务器类,继承 ResourceServerConfigurerAdapter 类,实现其中的 configure() 方法和 configure(ResourceServerSecurityConfigurer resources) 方法。

代码语言:javascript复制
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/api/**").authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .csrf().disable();
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("resource-server-rest-api").stateless(true);
    }
}

5. 创建安全配置类

创建一个安全配置类,继承 WebSecurityConfigurerAdapter 类,实现其中的 configure() 方法。

代码语言:javascript复制
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/oauth/token").permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable();
    }
}

6. 创建控制器

创建一个控制器类,实现一个简单的 RESTful API 接口。

代码语言:javascript复制
@RestController
@RequestMapping("/api")
public class ApiController {

    @GetMapping("/hello")
    public String hello() {
        return "Hello, World!";
    }

    @GetMapping("/user")
    public String user(Principal principal) {
        return "Hello, "   principal.getName();
    }
}

7. 运行测试

现在我们已经完成了 OAuth2 认证服务器和资源服务器的配置,可以启动项目并测试了。首先访问 http://localhost:8080/oauth/token ,传递以下参数进行认证:

代码语言:javascript复制
POST /oauth/token HTTP/1.1
Host: localhost:8080
Authorization: Basic Y2xpZW50YXBwOnNlY3JldA==
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=user&password=password

这将返回一个包含访问令牌和刷新令牌的 JSON 响应:

代码语言:javascript复制
{
    "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "token_type": "bearer",
    "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expires_in": 119,
    "scope": "openid read write"
}

接下来,我们可以使用这个访问令牌访问资源服务器的 API 接口,例如 http://localhost:8081/api/hello ,在请求头中加入以下内容:

代码语言:javascript复制
GET /api/hello HTTP/1.1
Host: localhost:8081
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

这将返回以下响应:

代码语言:javascript复制
Copy codeHello, World!

如果我们访问 http://localhost:8081/api/user ,在请求头中加入访问令牌,将返回以下响应:

代码语言:javascript复制
sqlCopy codeHello, user

这表示我们已经成功访问了受 OAuth2 保护的资源服务器。

0 人点赞