User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • Zookeeper
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • Python
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MinIO
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • Kafka
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
    • 摘要
    • 杂图
    • 问题随笔
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud Alibaba - 指南
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin中文版
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • Java 全栈知识体系
    • 尼恩架构师学习
    • 现代 JavaScript 教程
    • GO相关文档
    • Go学习导航
    • GoCN社区
    • GO极客兔兔-案例
    • 讯飞星火GPT
    • Hollis博客
    • PostgreSQL德哥
    • 优质博客推荐
    • 半兽人大佬
    • 系列教程
    • PostgreSQL文章
    • 云原生资料库
    • 并发博客大佬
Help?

Please contact us on our email for need any support

Support
    首页   ›   Spring   ›   SpringSecurity   ›   OAuth2   ›   正文
OAuth2

SpringSecurity—OAuth 2(八)客户端信息入库

2020-09-13 18:04:25
1066  0 0

阅读完需:约 5 分钟

还是根据授权码进行改造:

SpringSecurity—OAuth 2(二)授权码模式

客户端信息我们是直接存储在内存中的,像下面这样:

    //客户端详细信息服务配置
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()//在内存中
                //用户
                .withClient("xjh")
                //密码
                .secret(passwordEncoder.encode("123"))
                //资源编号
                .resourceIds("res1")
                //授权的赠款类型 authorization_code 授权码模式,refresh_token 刷新Token , implicit 简化模式 , password 密码模式 , 需要哪个模式就配置哪个模式
                .authorizedGrantTypes("authorization_code","refresh_token","implicit","password","client_credentials")
                //范围
                .scopes("all")
                //自动批准
                .autoApprove(true)
                //重定向Uris
                .redirectUris("http://localhost:8082/index.html","http://localhost:8082/password.html");
    }

然而在实际项目中,这种方式并不可取,一来客户端信息在代码中写死了,以后不好维护,而来我们的客户端信息可能量非常大,都写在代码里那你的代码该有多长呀(想象一下有多少第三方应用接入了微信登录)~

所以我们要将客户端信息存入数据库中。

客户端信息入库涉及到的接口主要是 ClientDetailsService,这个接口主要有两个实现类,如下:

InMemoryClientDetailsService 就不多说了,这是存在内存中的。如果要存入数据库,很明显是JdbcClientDetailsService,我们来大概看下 JdbcClientDetailsService 的源码,就能分析出数据库的结构了:

public class JdbcClientDetailsService implements ClientDetailsService, ClientRegistrationService {
    private static final Log logger = LogFactory.getLog(JdbcClientDetailsService.class);
    private JdbcClientDetailsService.JsonMapper mapper = createJsonMapper();
    private static final String CLIENT_FIELDS_FOR_UPDATE = "resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove";
    private static final String CLIENT_FIELDS = "client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove";
    private static final String BASE_FIND_STATEMENT = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details";
    private static final String DEFAULT_FIND_STATEMENT = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details order by client_id";
    private static final String DEFAULT_SELECT_STATEMENT = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details where client_id = ?";
    private static final String DEFAULT_INSERT_STATEMENT = "insert into oauth_client_details (client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove, client_id) values (?,?,?,?,?,?,?,?,?,?,?)";
    private static final String DEFAULT_UPDATE_STATEMENT = "update oauth_client_details set " + "resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove".replaceAll(", ", "=?, ") + "=? where client_id = ?";
    private static final String DEFAULT_UPDATE_SECRET_STATEMENT = "update oauth_client_details set client_secret = ? where client_id = ?";
    private static final String DEFAULT_DELETE_STATEMENT = "delete from oauth_client_details where client_id = ?";
    private RowMapper<ClientDetails> rowMapper = new JdbcClientDetailsService.ClientDetailsRowMapper();
    private String deleteClientDetailsSql = "delete from oauth_client_details where client_id = ?";
    private String findClientDetailsSql = "select client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove from oauth_client_details order by client_id";
    private String updateClientDetailsSql;
    private String updateClientSecretSql;
    private String insertClientDetailsSql;
    private String selectClientDetailsSql;
    private PasswordEncoder passwordEncoder;
    private final JdbcTemplate jdbcTemplate;
    private JdbcListFactory listFactory;

从这段简单的源码中,我们大概就能分析出表的结构

DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details` (
  `client_id` varchar(48) NOT NULL,
  `resource_ids` varchar(256) DEFAULT NULL,
  `client_secret` varchar(256) DEFAULT NULL,
  `scope` varchar(256) DEFAULT NULL,
  `authorized_grant_types` varchar(256) DEFAULT NULL,
  `web_server_redirect_uri` varchar(256) DEFAULT NULL,
  `authorities` varchar(256) DEFAULT NULL,
  `access_token_validity` int(11) DEFAULT NULL,
  `refresh_token_validity` int(11) DEFAULT NULL,
  `additional_information` varchar(4096) DEFAULT NULL,
  `autoapprove` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

接下来我们将一开始定义的客户端的关键信息存入数据库中,如下:

既然用到了数据库,依赖当然也要提供相应的支持,我们给 auth-server 添加如下依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

然后在 application.properties 中配置一下数据库的连接信息:

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/oauth2?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.password=123
spring.datasource.username=root
spring.main.allow-bean-definition-overriding=true

这里的配置多了最后一条。这是因为我们一会要创建自己的 ClientDetailsService,而系统已经创建了ClientDetailsService,加了最后一条就允许我们自己的实例覆盖系统默认的实例。

要做改变的地方AuthorizationServerConfig文件:

接下来,我们来提供自己的实例即可:

    /**
      数据源
    */
    @Autowired
    DataSource dataSource;
    @Bean
    ClientDetailsService clientDetailsService(){
        return new JdbcClientDetailsService(dataSource);
    }
    @Bean //授权服务器令牌服务
    AuthorizationServerTokenServices tokenServices(){
        //默认令牌服务
        DefaultTokenServices services=new DefaultTokenServices();
        //设置客户详细信息服务
        services.setClientDetailsService(clientDetailsService()); // 替换成我们的实例 clientDetailsService 
        //设置支持刷新令牌
        services.setSupportRefreshToken(true);
        //设置令牌存储
        services.setTokenStore(tokenStore);
        //设置访问令牌有效性秒数 在数据库里查询了不需要
//        services.setAccessTokenValiditySeconds(60*60*2); 
        //设置刷新令牌有效秒数  在数据库里查询了不需要
//        services.setRefreshTokenValiditySeconds(60*60*24*7);
        return services;
    }
    //客户端详细信息服务配置
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsService()); //数据库查询
//        clients.inMemory()//在内存中
//                //用户
//                .withClient("xjh")
//                //密码
//                .secret(passwordEncoder.encode("123"))
//                //资源编号
//                .resourceIds("res1")
//                //授权的赠款类型 authorization_code 授权码模式,refresh_token 刷新Token , implicit 简化模式 , password 密码模式
//                .authorizedGrantTypes("authorization_code","refresh_token","implicit","password","client_credentials")
//                //范围
//                .scopes("all")
//                //自动批准
////                .autoApprove(true)
//                //重定向Uris
//                .redirectUris("http://localhost:8082/index.html","http://localhost:8082/password.html");
    }

配置完成后,重启 auth-server,走一遍第三方登录流程,和我们前面效果一样。

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

0 打赏
Enamiĝu al vi
不要为明天忧虑.因为明天自有明天的忧虑.一天的难处一天当就够了。
543文章 68评论 294点赞 593937浏览

随机文章
SpringSecurity—OAuth 2(二)授权码模式
5年前
MyBatis笔记5—properties(外部配置)
5年前
MySQL—理解索引 (3)
3年前
Spring Boot 的配置文件 application.properties+多环境切换
5年前
SpringBoot DevTools—开发工具
5年前
博客统计
  • 日志总数:543 篇
  • 评论数目:68 条
  • 建站日期:2020-03-06
  • 运行天数:1927 天
  • 标签总数:23 个
  • 最后更新:2024-12-20
Copyright © 2025 网站备案号: 浙ICP备20017730号 身体没有灵魂是死的,信心没有行为也是死的。
主页
页面
  • 归档
  • 摘要
  • 杂图
  • 问题随笔
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
To be, or not to be
543 文章 68 评论 593937 浏览
测试
测试
看板娘
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付