介绍
Spring Security OAuth2 是一个在 Spring Security 框架基础上构建的 OAuth2 授权服务器和资源服务器的扩展库。它提供了一套功能强大的工具和组件,用于实现 OAuth2 协议中的授权流程、令牌管理和访问控制。
Git地址:yunfeng-boot3-sercurity: Spring Security OAuth2 统一登录(授权码模式)
版本
SpringBoot 2.5.6
OAuth2重要角色
- Authorization Server : 授权服务器。
- Resource Server: 资源服务器。举例针对微服务里面各个业务子系统:用户系统、商家系统、商品系统、订单系统等等。
- Client:客户端:浏览器、APP、小程序等等
具体实现
OAuth2 有多种授权模式。本实例中,使用授权码模式 + 授权服务器,来实现用户的认证。
主要接口:
- 获取授权码:http://localhost:8080/auth/oauth/authorize?response_type=code&client_id=hello&redirect_uri=http://localhost:8080&scope=all
- 获取token:http://localhost:8080/auth/oauth/token
首先,创建一个SpringBoot应用,作为授权服务器。集成SpringBoot 2.5.6 + MySQL + Spring Security + Redis。
- 配置AuthorizationServerConfigurerAdapter.
继承AuthorizationServerConfigurerAdapter 主要是针对授权服务器进行自定义配置。
- 配置token的接口权限,允许进行客户端授权。每个token都是跟某一个客户端进行关联的。所以MySQL里面
需要增加一张表,并配置好需要授权的客户端记录.
表结构如下:
CREATE TABLE `oauth_client_details` (
`client_id` varchar(256) COMMENT '客户端ID',
`resource_ids` varchar(256),
`client_secret` varchar(256) COMMENT '客户端密钥',
`scope` varchar(256),
`authorized_grant_types` varchar(256) COMMENT '授权类型',
`web_server_redirect_uri` varchar(256),
`authorities` varchar(256),
`access_token_validity` int(11) COMMENT 'access_token的有效时间',
`refresh_token_validity` int(11) COMMENT 'refresh_token的有效时间',
`additional_information` varchar(4096),
`autoapprove` varchar(256) COMMENT '是否允许自动授权',
PRIMARY KEY (`client_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
INSERT INTO `weef_iot_edge_shaoyifu`.`oauth_client_details` (`client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`) VALUES ('hello', 'order-resource', '$2a10Kc3YXJdKpWEtLFD.xBSlFO5.OD94MZ7zWdl9CiQ5OGlYvSuvM8qoi', 'all', 'authorization_code,password', 'http://localhost:8080', NULL, 3600, NULL, NULL, 'true');
授权服务器代码如下:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Resource
private DataSource dataSource;
@Resource
private RedisConnectionFactory redisConnectionFactory;
private final static String TOKEN_STORE_PREFIX = "yf-token-store";
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
// 开启/oauth/token_key验证端口无权限访问
security.tokenKeyAccess("permitAll()")
// 开启/oauth/check_token验证端口认证权限访问
.checkTokenAccess("isAuthenticated()").allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService());
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
tokenStore.setPrefix(TOKEN_STORE_PREFIX);
endpoints.tokenStore(tokenStore);
}
public ClientDetailsService clientDetailsService() {
return new JdbcClientDetailsService(dataSource);
}
}
- 配置WebSecurityConfigurerAdapter
继承WebSecurityConfigurerAdapter,来实现用户信息的配置。这个简化实现。内置了用户名和密码。通过这个类,可以扩展到使用MySQL来时实现,用户名和密码的校验。
同时,针对Spring Security 内置登录页面。也可以通过配置这个类,实现自定义的登录页面。
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("zhangsan")
.password(passwordEncoder().encode("123456")).roles("ADMIN")
.and().passwordEncoder(passwordEncoder());
System.out.println(passwordEncoder().encode("123456"));
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
- 获取code:通过浏览器访问:http://localhost:8080/auth/oauth/authorize?response_type=code&client_id=hello&redirect_uri=http://localhost:8080&scope=all
登录之后,可以拿到code
- 调用获取token接口: