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
@EnableAuthorizationServer
public 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

@Configuration
public 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-server
server.port=8762
spring.main.allow-bean-definition-overriding=true
​
logging.level.root = info
loggin.level.org.springframework.web = info
​
server.servlet.context-path=/oauth
​
​
# 数据源配置 start
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud-oauth2?useUnicode=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#durid登陆账号密码
loginUsername=root
loginPassword=root
# 下面为连接池的补充设置,应用到上面所有数据源中
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙,防止sql注入
spring.datasource.filters=stat,wall,log4j
spring.datasource.logSlowSql=true
# 数据源配置end
​
eureka.client.enabled=false
eureka.client.allow-redirects=false
eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka/
eureka.instance.preferIpAddress = true
eureka.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,env
​
feign.hystrix.enabled=true
feign.compression.request.enabled=true
feign.compression.request.mime-types[0]=text/html
feign.compression.request.mime-types[1]=application/xml
feign.compression.request.mime-types[2]=application/json
feign.compression.request.min-request-size=2048
feign.compression.response.enabled=true#mybatis-plus配置控制台打印完整带参数SQL语句
#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
​
security.oauth2.client.access-token-uri=http://localhost:8762/auth/oauth/token
security.oauth2.client.user-authorization-uri=http://localhost:8762/auth/oauth/authorize
security.oauth2.client.authorized-grant-types=authorization_code
security.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
@Slf4j
public 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,欢迎继续关注下一篇客户资源服务器搭建

 

 

posted @   微信公众号-醉鱼Java  阅读(133)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示