SpringCloud Oauth2.0 实现资源验证

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: SpringCloud Oauth2.0 实现资源验证

前提

* JDK1.8

* SpringCloud Greenwich.RELEASE

* SpringBoot 2.1.8.RELEASE

先看一下项目结构

 

现在开始搭建,首先建立一个maven项目,即父maven工程,pom文件内容如下

<parent>        <artifactId>spring-boot-starter-parent</artifactId>        <groupId>org.springframework.boot</groupId>        <version>2.1.8.RELEASE</version>    </parent>    <properties>    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>    <java.version>1.8</java.version>    <mysql.version>8.0.16</mysql.version>    </properties>     <packaging>pom</packaging><dependencyManagement>        <dependencies>            <!--  控制spring-cloud版本          -->            <dependency>                <groupId>org.springframework.cloud</groupId>                <artifactId>spring-cloud-dependencies</artifactId>                <version>Greenwich.RELEASE</version>                <type>pom</type>                <scope>import</scope>            </dependency>            <dependency>                <groupId>javax.servlet</groupId>                <artifactId>javax.servlet-api</artifactId>                <version>3.1.0</version>                <scope>provided</scope>            </dependency>            <dependency>                <groupId>com.alibaba</groupId>                <artifactId>fastjson</artifactId>                <version>1.2.54</version>            </dependency>            <dependency>                <groupId>org.projectlombok</groupId>                <artifactId>lombok</artifactId>                <version>1.18.10</version>            </dependency>            <dependency>                <groupId>mysql</groupId>                <artifactId>mysql-connector-java</artifactId>                <version>8.0.18</version>            </dependency>            <dependency>                <groupId>org.springframework.security</groupId>                <artifactId>spring-security-jwt</artifactId>                <version>1.0.11.RELEASE</version>            </dependency>            <dependency>                <groupId>org.springframework.security.oauth.boot</groupId>                <artifactId>spring-security-oauth2-autoconfigure</artifactId>                <version>2.0.1.RELEASE</version>            </dependency>        </dependencies>    </dependencyManagement>    <dependencies>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>${mysql.version}</version>            <scope>runtime</scope>        </dependency>        <!--druid依赖-->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid</artifactId>            <version>1.1.3</version>        </dependency>        <dependency>            <groupId>com.baomidou</groupId>            <artifactId>mybatis-plus-boot-starter</artifactId>            <version>3.2.0</version>        </dependency>        <!--代码生成-->        <dependency>            <groupId>com.baomidou</groupId>            <artifactId>mybatis-plus-generator</artifactId>            <version>3.2.0</version>        </dependency>        <!--swagger 文档注释-->        <dependency>            <groupId>io.springfox</groupId>            <artifactId>springfox-swagger2</artifactId>            <version>2.7.0</version>        </dependency>        <dependency>            <groupId>io.springfox</groupId>            <artifactId>springfox-swagger-ui</artifactId>            <version>2.7.0</version>        </dependency>        <!--swagger-->        <!--fast-json-->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>        </dependency>        <!--lombok-->        <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>        </dependency>        <!--log4j druid使用-->        <dependency>            <groupId>log4j</groupId>            <artifactId>log4j</artifactId>            <version>1.2.17</version>        </dependency>        <!--健康检查-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-actuator</artifactId>        </dependency>    </dependencies>

此处引入了基本都需要使用的依赖,并使用dependencyManagement 固定使用依赖的版本

下面开始搭建授权服务

新建springBoot工程,pom如下,指定父pom为上面的文件,并引入auth需要的jar包,

<parent>        <groupId>com.tz</groupId>        <artifactId>spring-cloud</artifactId>        <version>1.0-SNAPSHOT</version>    </parent><dependencies>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-freemarker</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>        <!--   断路器     -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>        </dependency>        <dependency>            <groupId>com.netflix.hystrix</groupId>            <artifactId>hystrix-javanica</artifactId>        </dependency>        <!--  ribbon     -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>        </dependency>        <!--   feign     -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-openfeign</artifactId>        </dependency>        <!-- 重试机制       -->        <dependency>            <groupId>org.springframework.retry</groupId>            <artifactId>spring-retry</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.data</groupId>            <artifactId>spring-data-commons</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-security</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-oauth2</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.security</groupId>            <artifactId>spring-security-jwt</artifactId>        </dependency>        <dependency>            <groupId>javax.interceptor</groupId>            <artifactId>javax.interceptor-api</artifactId>            <version>1.2</version>        </dependency>    </dependencies>

配置AuthorizationServer

@Configuration@EnableAuthorizationServerpublic class AuthorizationServer extends AuthorizationServerConfigurerAdapter {    /**     * 令牌存储     */    @Autowired    private TokenStore tokenStore;    /**     * 客户端管理     */    @Autowired    private ClientDetailsService clientDetailsService;    @Autowired    private AuthorizationCodeServices authorizationCodeServices;    @Autowired    private AuthenticationManager authenticationManager;    /**     * A 配置客户端详情,支持哪些客户端     * @param clients     * @throws Exception     */    @Override    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {        clients.inMemory()                // 客户端id                .withClient("c1")                // 客户端密钥                .secret(new BCryptPasswordEncoder().encode("secret"))                // 资源列表                .resourceIds("res1")                // 该client允许的授权类型,                .authorizedGrantTypes("authorization_code","password","client_credentials",                        "implicit","refresh_token")                // 允许的授权范围,就是一个标识,read,write                .scopes("all")                .autoApprove(false)                // 验证回调地址                .redirectUris("http://www.baidu.com");    }    /**     * B 令牌访问端点,即url     * @param endpoints     * @throws Exception     */    @Override    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {        endpoints                // 密码模式需要                .authenticationManager(authenticationManager)                // 授权码模式需要                .authorizationCodeServices(authorizationCodeServices)                // 令牌管理服务                .tokenServices(tokenServices())                //允许post提交                .allowedTokenEndpointRequestMethods(HttpMethod.POST);    }    /**     * C 配置令牌端点 安全约束     * @param security     * @throws Exception     */    @Override    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {        security                // /oauth/token_key  url 公开                .tokenKeyAccess("permitAll()")                // /oauth/check_token 公开                .checkTokenAccess("permitAll()")                // 表单验证,申请令牌                .allowFormAuthenticationForClients();    }    /**     * D 定义tokenServices     * @return     */    @Bean    public AuthorizationServerTokenServices tokenServices(){        DefaultTokenServices services = new DefaultTokenServices();        services.setClientDetailsService(clientDetailsService);        services.setSupportRefreshToken(true);        services.setTokenStore(tokenStore);        // 令牌默认有限期2小时        services.setAccessTokenValiditySeconds(7200);        // 刷新令牌默认有限期3天        services.setRefreshTokenValiditySeconds(259200);        return services;    }    /**     * 设置授权码如何存储     * @param     * @return     */    @Bean    public AuthorizationCodeServices authorizationCodeServices() {        return new InMemoryAuthorizationCodeServices();    }}

定义令牌存储方式,TokenConfig

@Configurationpublic class TokenConfig {    /**     *     令牌存储测试     */    @Bean    public TokenStore tokenStore(){        // 内存方式,普通令牌        return new InMemoryTokenStore();    }}

定义web配置,配置拦截url

@Configuration@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)public class WebSecurityConfig extends WebSecurityConfigurerAdapter {    /**     * 认证管理器     * @return     * @throws Exception     */    @Bean    @Override    public AuthenticationManager authenticationManager() throws Exception{        return super.authenticationManager();    }    /**     * 密码编码器     * @return     */    @Bean    public PasswordEncoder passwordEncoder(){        return new BCryptPasswordEncoder();    }    /**     * D 安全拦截机制     * @param http     * @throws Exception     */    @Override    protected void configure(HttpSecurity http) throws Exception {        // 关闭csrf        http.csrf().disable()                // 开启验证                .authorizeRequests()                // 访问/r/r1需要p1                .antMatchers("/r/r1").hasAnyAuthority("p1")                // login* 不需要拦截                .antMatchers("/login*").permitAll()                // 其他的url都需要拦截                .anyRequest().authenticated()                .and()                // 支持表单登录                .formLogin();    }}

application.properties

因为引入了数据源,所以此处需要配置,但是此时没有用到,后续用到时使用

spring.application.name=oauth-serverserver.port=8762spring.main.allow-bean-definition-overriding=truelogging.level.root = infologgin.level.org.springframework.web = infoserver.servlet.context-path=/oauth# 数据源配置 startspring.datasource.url=jdbc:mysql://localhost:3306/springcloud-oauth2?useUnicode=truespring.datasource.username=rootspring.datasource.password=rootspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.type=com.alibaba.druid.pool.DruidDataSource#durid登陆账号密码loginUsername=rootloginPassword=root# 下面为连接池的补充设置,应用到上面所有数据源中spring.datasource.initialSize=5spring.datasource.minIdle=5spring.datasource.maxActive=20# 配置获取连接等待超时的时间spring.datasource.maxWait=60000# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒spring.datasource.timeBetweenEvictionRunsMillis=60000# 配置一个连接在池中最小生存的时间,单位是毫秒spring.datasource.minEvictableIdleTimeMillis=300000spring.datasource.validationQuery=SELECT 1 FROM DUALspring.datasource.testWhileIdle=truespring.datasource.testOnBorrow=falsespring.datasource.testOnReturn=false# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙,防止sql注入spring.datasource.filters=stat,wall,log4jspring.datasource.logSlowSql=true# 数据源配置endeureka.client.enabled=falseeureka.client.allow-redirects=falseeureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka/eureka.instance.preferIpAddress = trueeureka.instance.instance-id = ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}}management.endpoints.web.exposure.include=refresh,health,info,envfeign.hystrix.enabled=truefeign.compression.request.enabled=truefeign.compression.request.mime-types[0]=text/htmlfeign.compression.request.mime-types[1]=application/xmlfeign.compression.request.mime-types[2]=application/jsonfeign.compression.request.min-request-size=2048feign.compression.response.enabled=true#mybatis-plus配置控制台打印完整带参数SQL语句#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImplsecurity.oauth2.client.access-token-uri=http://localhost:8762/auth/oauth/tokensecurity.oauth2.client.user-authorization-uri=http://localhost:8762/auth/oauth/authorizesecurity.oauth2.client.authorized-grant-types=authorization_codesecurity.oauth2.resource.user-info-uri=http://localhost:8780/dashboard/user

客户端模式,post 请求获取token

http://127.0.0.1:8762/oauth/oauth/token?client_id=c1&client_secret=secret&grant_type=client_credentials

返回结果如下

 

用户名密码模式

定义userDetailService

@Service@Slf4jpublic class MyUserDetailService implements UserDetailsService {        @Override    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {                // 用户名tz,密码123        UserDetails userDetails = User.withUsername("tz").password("$2a$10$pTffBwh9mawjeGG9K5ZhbenBfWQRV1aFVgZqVt59eM67iJhDqARyG").authorities("p1").build();        return userDetails;    }

加密的密码生成,生成的密码每次都不一样,但是都代表123

@Test    public void createBCryptPw(){        String gensalt = BCrypt.gensalt();        System.out.println(gensalt);        String hashpw = BCrypt.hashpw("123", gensalt);        System.out.println(hashpw);    }

用户名密码 post 请求,会返回refresh_token

http://127.0.0.1:8762/oauth/oauth/token?client_id=c1&client_secret=secret&username=tz&password=123&grant_type=password

返回结果

好了,授权服务器简单模式搭建完成,详细点击原文链接查看README,欢迎继续关注下一篇客户资源服务器搭建

 

 

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
打赏
0
0
0
0
186
分享
相关文章
AI 时代:从 Spring Cloud Alibaba 到 Spring AI Alibaba
本次分享由阿里云智能集团云原生微服务技术负责人李艳林主讲,主题为“AI时代:从Spring Cloud Alibaba到Spring AI Alibaba”。内容涵盖应用架构演进、AI agent框架发展趋势及Spring AI Alibaba的重磅发布。分享介绍了AI原生架构与传统架构的融合,强调了API优先、事件驱动和AI运维的重要性。同时,详细解析了Spring AI Alibaba的三层抽象设计,包括模型支持、工作流智能体编排及生产可用性构建能力,确保安全合规、高效部署与可观测性。最后,结合实际案例展示了如何利用私域数据优化AI应用,提升业务价值。
162 4
轻松掌握Spring依赖注入:打造你的登录验证系统
本文以轻松活泼的风格,带领读者走进Spring框架中的依赖注入和登录验证的世界。通过详细的步骤和代码示例,我们从DAO层的创建到Service层的实现,再到Spring配置文件的编写,最后通过测试类验证功能,一步步构建了一个简单的登录验证系统。文章不仅提供了实用的技术指导,还以口语化和生动的语言,让学习变得不再枯燥。
56 2
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
212 5
【Spring Cloud生态】Spring Cloud Gateway基本配置
【Spring Cloud生态】Spring Cloud Gateway基本配置
81 0
【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
112 1
【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等