- 通过刷新令牌获取访问令牌
- 新建CustomUserDetailsService
| @Component("customUserDetailsService") |
| public class CustomUserDetailsService implements UserDetailsService { |
| @Autowired |
| private PasswordEncoder passwordEncoder; |
| @Override |
| public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { |
| return new User("admin", passwordEncoder.encode("1234"), |
| AuthorityUtils.commaSeparatedStringToAuthorityList("product")); |
| } |
| } |
- SpringSecurityConfig中添加如下
| @Autowired |
| private UserDetailsService customUserDetailsService; |
| |
| @Override |
| protected void configure(AuthenticationManagerBuilder auth) throws Exception { |
| auth.userDetailsService(customUserDetailsService); |
| } |
- AuthorizationServerConfig中添加如下
| @Autowired |
| private UserDetailsService customUserDetailsService; |
| |
| @Override |
| public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { |
| |
| endpoints.authenticationManager(authenticationManager); |
| |
| endpoints.userDetailsService(customUserDetailsService); |
| } |
-
postmam测试


-
使用jdbc管理访问令牌
-
新建数据库和表

| |
| |
| |
| DROP TABLE IF EXISTS `clientdetails`; |
| CREATE TABLE `clientdetails` ( |
| `appId` varchar(128) NOT NULL, |
| `resourceIds` varchar(128) DEFAULT NULL, |
| `appSecret` varchar(128) DEFAULT NULL, |
| `scope` varchar(128) DEFAULT NULL, |
| `grantTypes` varchar(128) DEFAULT NULL, |
| `redirectUrl` varchar(128) DEFAULT NULL, |
| `authorities` varchar(128) DEFAULT NULL, |
| `access_token_validity` int(11) DEFAULT NULL, |
| `refresh_token_validity` int(11) DEFAULT NULL, |
| `additionalInformation` varchar(4096) DEFAULT NULL, |
| `autoApproveScopes` varchar(128) DEFAULT NULL, |
| PRIMARY KEY (`appId`) |
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
| |
| |
| |
| |
| |
| |
| |
| |
| DROP TABLE IF EXISTS `oauth_access_token`; |
| CREATE TABLE `oauth_access_token` ( |
| `token_id` varchar(128) DEFAULT NULL, |
| `token` blob, |
| `authentication_id` varchar(128) NOT NULL, |
| `user_name` varchar(128) DEFAULT NULL, |
| `client_id` varchar(128) DEFAULT NULL, |
| `authentication` blob, |
| `refresh_token` varchar(128) DEFAULT NULL, |
| PRIMARY KEY (`authentication_id`) |
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
| |
| |
| |
| |
| |
| |
| |
| |
| DROP TABLE IF EXISTS `oauth_approvals`; |
| CREATE TABLE `oauth_approvals` ( |
| `userId` varchar(128) DEFAULT NULL, |
| `clientId` varchar(128) DEFAULT NULL, |
| `scope` varchar(128) DEFAULT NULL, |
| `status` varchar(10) DEFAULT NULL, |
| `expiresAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
| `lastModifiedAt` timestamp NOT NULL |
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
| |
| |
| |
| |
| |
| |
| |
| |
| DROP TABLE IF EXISTS `oauth_client_details`; |
| CREATE TABLE `oauth_client_details` ( |
| `client_id` varchar(128) NOT NULL COMMENT '客户端id(如:mengxuegu_client', |
| `resource_ids` varchar(128) DEFAULT NULL, |
| `client_secret` varchar(128) DEFAULT NULL COMMENT '客户端密码(要加密后存储)', |
| `scope` varchar(128) DEFAULT NULL COMMENT '客户端授权范all,write,read)', |
| `authorized_grant_types` varchar(128) DEFAULT NULL COMMENT '4种授权类型(多个授权类型,用英文逗号分隔', |
| `web_server_redirect_uri` varchar(128) DEFAULT NULL COMMENT '获取授权码后的回调地址', |
| `authorities` varchar(128) DEFAULT NULL COMMENT '授权标识', |
| `access_token_validity` int(11) DEFAULT NULL, |
| `refresh_token_validity` int(11) DEFAULT NULL, |
| `additional_information` varchar(4096) DEFAULT NULL, |
| `autoapprove` varchar(128) DEFAULT NULL, |
| PRIMARY KEY (`client_id`) |
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户端(第三方应用)基本信息'; |
| |
| |
| |
| |
| INSERT INTO `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 ('mengxuegu-pc', 'product-server', '$2a$10$VcUHxmgnxBTdB9XNdhoOWujC.lFZ0rO1UizqMAS0GU6WAerFviX.a', 'all,PRODUCT_API', 'authorization_code,password,implicit,client_credentials,refresh_token', 'http://www.mengxuegu.com/', NULL, '50000', NULL, NULL, 'false'); |
| INSERT INTO `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 ('client1', '', '$2a$10$AodcXpujNILcZAQ.7cQ0b.Bm4klRumapoFBu7uyQ/ZV9Nu9F5fE3y', 'MEMBER_READ,MEMBER_WRITE', 'authorization_code,refresh_token', 'http://localhost:9001/login', NULL, '50000', NULL, NULL, 'true'); |
| INSERT INTO `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 ('client2', '', '$2a$10$AodcXpujNILcZAQ.7cQ0b.Bm4klRumapoFBu7uyQ/ZV9Nu9F5fE3y', 'MEMBER_READ', 'authorization_code,refresh_token', 'http://localhost:9002/login', NULL, '50000', NULL, NULL, 'true'); |
| |
| |
| |
| |
| |
| DROP TABLE IF EXISTS `oauth_client_token`; |
| CREATE TABLE `oauth_client_token` ( |
| `token_id` varchar(128) DEFAULT NULL, |
| `token` blob, |
| `authentication_id` varchar(128) NOT NULL, |
| `user_name` varchar(128) DEFAULT NULL, |
| `client_id` varchar(128) DEFAULT NULL, |
| PRIMARY KEY (`authentication_id`) |
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
| |
| |
| |
| |
| |
| |
| |
| |
| DROP TABLE IF EXISTS `oauth_code`; |
| CREATE TABLE `oauth_code` ( |
| `code` varchar(128) DEFAULT NULL, |
| `authentication` blob |
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
| |
| |
| |
| |
| |
| |
| |
| |
| DROP TABLE IF EXISTS `oauth_refresh_token`; |
| CREATE TABLE `oauth_refresh_token` ( |
| `token_id` varchar(128) DEFAULT NULL, |
| `token` blob, |
| `authentication` blob |
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
| <dependency> |
| <groupId>com.baomidou</groupId> |
| <artifactId>mybatis-plus-boot-starter</artifactId> |
| </dependency> |
| <dependency> |
| <groupId>org.springframework.boot</groupId> |
| <artifactId>spring-boot-starter-jdbc</artifactId> |
| </dependency> |
| |
| <dependency> |
| <groupId>com.alibaba</groupId> |
| <artifactId>druid</artifactId> |
| </dependency> |
| <dependency> |
| <groupId>mysql</groupId> |
| <artifactId>mysql-connector-java</artifactId> |
| </dependency> |
| spring: |
| |
| datasource: |
| username: root |
| password: 123456 |
| url: jdbc:mysql://192.168.1.102:3306/demo?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8 |
| |
| driver-class-name: com.mysql.cj.jdbc.Driver |
| |
| initialSize: 8 |
| minIdle: 5 |
| maxActive: 20 |
| maxWait: 60000 |
| timeBetweenEvictionRunsMillis: 60000 |
| minEvictableIdleTimeMillis: 300000 |
| validationQuery: SELECT 1 FROM DUAL |
| @Configuration |
| public class TokenConfig { |
| |
| @ConfigurationProperties(prefix = "spring.datasource") |
| @Bean |
| public DataSource dataSource(){ |
| return new DruidDataSource(); |
| } |
| @Bean |
| public TokenStore tokenStore() { |
| |
| return new JdbcTokenStore(dataSource()); |
| } |
| } |
| |
| # AuthorizationServerConfig类中添加如下 |
| @Autowired |
| private TokenStore tokenStore; |
| @Override |
| public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { |
| |
| endpoints.tokenStore(tokenStore); |
| } |
-
启动项目使用密码模式测试

-
数据库中产生1条数据,测试通过

-
jdbc管理授权码
| # AuthorizationServerConfig配置类中添加如下 |
| @Autowired |
| private DataSource dataSource; |
| @Bean |
| public AuthorizationCodeServices jdbcAuthorizationCodeServices() { |
| return new JdbcAuthorizationCodeServices(dataSource); |
| } |
| @Override |
| public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { |
| |
| endpoints.authorizationCodeServices(jdbcAuthorizationCodeServices()); |
| } |
| |
| # 之前的客户端信息储存在内存中,将其注释掉 |
| @Override |
| public void configure(ClientDetailsServiceConfigurer clients) throws Exception { |
| clients.inMemory() |
| .withClient("mengxuegu-pc") |
| .secret(passwordEncoder.encode("mengxuegu-secret")) |
| .resourceIds("product-server") |
| .authorizedGrantTypes("authorization_code", "password", "implicit", "client_credentials", "refresh_token") |
| .scopes("all") |
| .autoApprove(false) |
| .redirectUris("http://www.mengxuegu.com/") |
| .accessTokenValiditySeconds(60*60*8) |
| .refreshTokenValiditySeconds(60*60*24*60) |
| ; |
| } |
- 未获取授权码前查看数据库

- 获取授权码
| # 浏览器访问http://localhost:8090/auth/oauth/authorize?client_id=mengxuegu-pc&response_type=code |
| # 输入用户名和密码:admin + 1234 |

-
获取授权码后查看数据库

-
使用授权码后,数据库自动删除授权码


-
配置访问令牌和刷新令牌的有效时长
| @Override |
| public void configure(ClientDetailsServiceConfigurer clients) throws Exception { |
| |
| clients.inMemory() |
| .withClient("mengxuegu-pc") |
| .secret(passwordEncoder.encode("mengxuegu-secret")) |
| .resourceIds("product-server") |
| .authorizedGrantTypes("authorization_code", "password", "implicit", "client_credentials", "refresh_token") |
| .scopes("all") |
| .autoApprove(false) |
| .redirectUris("http://www.mengxuegu.com/") |
| .accessTokenValiditySeconds(60*60*8) |
| .refreshTokenValiditySeconds(60*60*24*60) |
| ; |
| } |
oauth_client_details表字段详情
| client_id :客户端ID |
| resource_ids :可访问的资源服务器ID, 不写则不校验. |
| client_secret :客户端密码,此处不能是明文,需要加密$2a$10$VcUHxmgnxBTdB9XNdhoOWujC.lFZ0rO1UizqMAS0GU6WAerFviX.a |
| scope :客户端授权范围, 不指定默认不校验范围 |
| authorized_grant_types :客户端授权类型,支持多个使用逗号分隔authorization_code,password,implicit,client_credentials,refresh_token |
| web_server_redirect_uri :服务器回调地址 |
| autoapprove :false 显示授权点击页,true不显示自动授权 |
| # AuthorizationServerConfig类中添加如下 |
| @Autowired |
| private DataSource dataSource; |
| @Bean |
| public ClientDetailsService jdbcClientDetailsService() { |
| return new JdbcClientDetailsService(dataSource); |
| } |
| |
| |
| |
| |
| |
| |
| |
| @Override |
| public void configure(ClientDetailsServiceConfigurer clients) throws Exception { |
| |
| clients.withClientDetails(jdbcClientDetailsService()); |
| } |
-
使用postman测试

-
令牌端点详情
| /oauth/authorize :申请授权码 code, 涉及的类 AuthorizationEndpoint |
| /oauth/token :获取令牌 token, 涉及的类 TokenEndpoint |
| /oauth/check_token :用于资源服务器请求端点来检查令牌是否有效, 涉及的类 CheckTokenEndpoint |
| /oauth/confirm_access :用户确认授权提交, 涉及的类 WhitelabelApprovalEndpoint |
| /oauth/error :授权服务错误信息, 涉及的类 WhitelabelErrorEndpoint |
| /oauth/token_key :提供公有密匙的端点,使用 JWT 令牌时会使用 , 涉及的类 TokenKeyEndpoint |
| |
| |
| |
| |
| |
| @Override |
| public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { |
| |
| security.tokenKeyAccess("permitAll()"); |
| |
| security.checkTokenAccess("isAuthenticated()"); |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术