【oauth2】建一个spring cloud oauth2 Demo

spring cloud oauth2和spring security oauth2的区别

是 Spring Cloud 按照 OAuth2 的标准并结合 spring-security 封装好的一个具体实现。更多知识可以参考下面的文章

【权限----对比】深入理解Spring Cloud Security、OAuth2、JWT_Sunny3096的博客-CSDN博客_shiro和oauth2区别

spring-oauth父工程引用依赖

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/>
    </parent>    
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

spring-oauth2-client子工程

端口:8083

0、引入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
         </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
    </dependencies>

有需要注意的是:spring的版本不能高于spring-cloud,且spring-security-oauth2的2.0.2版本会报RedisConnection.set([B[B)V错误。

2、Config

(1)Oauth2Config

@Configuration
@EnableAuthorizationServer
public class Oauth2Config extends AuthorizationServerConfigurerAdapter {
    @Autowired
    public PasswordEncoder passwordEncoder;
    @Autowired
    public UserDetailsService myUserService;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private TokenStore redisTokenStore;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients();
        security.tokenKeyAccess("isAuthenticated()");
        //这个一定要开允许,否则/oauth/check_token会报403的错误
        security.checkTokenAccess("permitAll()");
    }

    //配置在内存时存放的格式
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client_id")
                .resourceIds("rid")
                .secret(passwordEncoder.encode("secret"))
                .authorizedGrantTypes("refresh_token", "authorization_code", "password")
                .accessTokenValiditySeconds(3600)
                .scopes("all");
    }

    //配置Userdetail的格式和redis
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(myUserService)
                .tokenStore(redisTokenStore);
    }
}

注意:security.checkTokenAccess("permitAll()");这个一定要开允许,否则/oauth/check_token会报403的错误

(2)RedisTokenStoreConfig

注入redisTokenStore这个Bean,如果需要改redis存放token时的前缀,也可以在这个地方改

@Configuration
public class RedisTokenStoreConfig {
    @Autowired
    RedisConnectionFactory redisConnectionFactory;

    @Bean
    public TokenStore redisTokenStore(){
        return new RedisTokenStore(redisConnectionFactory);
    }
}

(3)WebSecurityConfig

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    //重新注入password加密的Bean,采用BCry加密方法
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 允许所有匿名访问接口
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/oauth/**")
                .authorizeRequests()
                .antMatchers("/oauth/**").permitAll()
                //解决跨域
                .and().csrf().disable();
    }
}


3、UserDetail改写

本Demo没有连接数据库,loadUserByUsername()方法中应该放入数据库的查询操作,本Demo固定写好账户

@Component(value = "myUserService")
public class MyUserService implements UserDetailsService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("username:"+username);
        if(!username.equals("admin")){
            throw new UsernameNotFoundException("not found username");
        }else{
            String role="ADMIN";
            ArrayList<SimpleGrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority(role));
            System.out.println("have add admin role");
            String password=passwordEncoder.encode("123");
            return new org.springframework.security.core.userdetails.User(username,password,authorities);
        }
    }
}

4、application.yml需要将redis配置好 

其他服务子工程-调用Oauth2

端口:8084

0、application.yml 根据Oauth2的子工程填写

security:
  oauth2:
    client:
      client-id: client_id
      client-secret: secret
      user-authorization-uri: http://localhost:8083/oauth/authorize
      access-token-uri: http://localhost:8083/oauth/token
    resource:
      id: rid
      user-info-uri: user-info
    authorization:
      check-token-access: http://localhost:8083/oauth/check_token

上图中的url都是调用Oauth2工程中的地址,注意端口

1、ResourceServerConfig资源服务器配置

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Value("${security.oauth2.client.client-id}")
    private String clientId;

    @Value("${security.oauth2.client.client-secret}")
    private String secret;

    @Value("${security.oauth2.authorization.check-token-access}")
    private String checkTokenEndpointUrl;

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Bean
    public TokenStore redisTokenStore(){
       return new RedisTokenStore(redisConnectionFactory);
    }

    public RemoteTokenServices tokenServices(){
        RemoteTokenServices tokenServices = new RemoteTokenServices();
        tokenServices.setClientId(clientId);
        tokenServices.setClientSecret(secret);
        tokenServices.setCheckTokenEndpointUrl(checkTokenEndpointUrl);
        return tokenServices;
    }

    //配置资源服务器
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("rid")
                .tokenServices(tokenServices());
    }
}

2、Controller测试

@RestController
public class UserController {
    @GetMapping("/get")
    public Object get(Authentication authentication){
        authentication.getCredentials();
        OAuth2AuthenticationDetails details =(OAuth2AuthenticationDetails) authentication.getDetails();
        String token = details.getTokenValue();
        return token;
    }
}

流程:1、启动oauth2客户端 2、启动子服务

POSTMAN调用

因为在Oauth2Config中配置了security.allowFormAuthenticationForClients();允许表单认证,所以可以在body的form中填入以下信息

结果:

将token填入另一个工程的Authorization中

 

结果:返回token成功

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值