OAuth2授权服务器和四种授权方式
1 问题描述
OAuth协议主要是解决授权的问题,该协议定义了四种授权方式:授权码授权方式(最重要)、密码授权方式、简化授权方式、客户端授权方式,本文主要是基于Spring-Security-OAuth实现授权服务器和四种授权方式的配置与使用。
2 授权服务器实现
本文的授权服务器主要是基于JWT令牌(授权服务器端无需存储)使用四种授权方式进行授权,并且基于内存来存储授权客户端的信息,当然为了在授权之前能够进行用户认证,还整合了Spring Security的用户认证功能。
本文主要是分享授权服务器和四种授权方式的配置与应用,所以只展示了授权服务器工程,而省略了资源服务器工程,同时也省略了eureka服务注册中心工程和common-model公共实体类工程。
资源服务器的具体实现请见文章:OAuth2资源服务器
2.1 创建工程
创建一个名为auth-server的spring cloud微服务工程,项目结构如下图所示:
版本说明:
- Spring boot: 2.1.3
- Spring Cloud: Greenwich.SR1
- jdk: 1.8
2.2 授权相关的配置
通过@EnableAuthorizationServer启用OAuth授权服务器,授权服务器配置类AuthorizationServerConfig代码如下所示:
package com.auth.server.authorization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
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.configuration.EnableAuthorizationServer;
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.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
/**
* OAuth的授权服务器配置
* 注意:必须继承AuthorizationServerConfigurerAdapter类,并使用@Configuration和@EnableAuthorizationServer注解
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsService userDetailsServiceImpl;
/**
* 授权服务器安全配置:
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
/**
* 获取令牌不需要认证,校验令牌需要认证,允许表单认证
*/
security
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
}
/**
* 颁发令牌的客户端配置:
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
/**
* 在内存中添加四个客户端配置(还可以在数据库中配置):
* client_1只能使用授权码授权方式和刷新令牌的方式获取令牌
* client_2只能使用密码授权方式和刷新令牌的方式获取令牌
* client_3只能使用简化授权方式获取令牌
* client_4只能使用客户端授权方式获取令牌
*/
clients
.inMemory()
.withClient("client_1")
.secret(passwordEncoder.encode("secret_1"))
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(604800)
.authorizedGrantTypes("authorization_code", "refresh_token")
.redirectUris("http://baidu.com")
.scopes("all")
.and()
.withClient("client_2")
.secret(passwordEncoder.encode("secret_2"))
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(604800)
.authorizedGrantTypes("password", "refresh_token")
.scopes("all")
.and()
.withClient("client_3")
.secret(passwordEncoder.encode("secret_3"))
.accessTokenValiditySeconds(3600)
.authorizedGrantTypes("implicit")
.redirectUris("http://baidu.com")
.scopes("all")
.and()
.withClient("client_4")
.secret(passwordEncoder.encode("secret_4"))
.accessTokenValiditySeconds(3600)
.authorizedGrantTypes("client_credentials")
.scopes("all");
}
/**
* 授权服务器端点配置:
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) th