SpringCloud Oauth2.0 实现资源验证

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 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,欢迎继续关注下一篇客户资源服务器搭建

 

 

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
28天前
|
JSON 安全 算法
|
1月前
|
负载均衡 Java API
【Spring Cloud生态】Spring Cloud Gateway基本配置
【Spring Cloud生态】Spring Cloud Gateway基本配置
37 0
|
3月前
|
Java Spring
【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.
|
3月前
|
Java Spring 容器
【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
|
3月前
|
存储 Java Spring
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
|
3月前
|
SQL Java 数据库连接
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
|
3月前
|
Java 开发工具 Spring
【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
|
3月前
|
NoSQL Java Redis
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常
|
3月前
|
Java Spring
【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
【Azure 应用服务】记一次Azure Spring Cloud 的部署错误 (az spring-cloud app deploy -g dev -s testdemo -n demo -p ./hellospring-0.0.1-SNAPSHOT.jar --->>> Failed to wait for deployment instances to be ready)
|
3月前
|
Java Maven Python
【Azure Spring Cloud】部署Azure spring cloud 失败
【Azure Spring Cloud】部署Azure spring cloud 失败