码迷,mamicode.com
首页 > 编程语言 > 详细

使用SpringSecurityOAuth2配置自定义Token实现OAuth2授权示例

时间:2020-06-13 19:06:37      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:bsp   extend   htm   secret   请求   方式   rop   frame   HCL   

  本文记录一下使用SpringSecurityOAuth2配置自定义Token实现OAuth2授权的步骤

  1、相关知识

  OAuth协议简介:https://www.cnblogs.com/javasl/p/13054133.html

  OAuth 2.0官网:https://oauth.net/2/

  使用SpringSecurityOAuth2默认实现OAuth2授权示例:https://www.cnblogs.com/javasl/p/13060284.html

  2、构建项目

  本文使用的springboot版本是2.0.4.RELEASE,不同版本可能会有所区别。下面是主要的配置文件和类:

  1)pom依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
<dependency>
    <groupId>org.springframework.security.oauth.boot</groupId>
    <artifactId>spring-security-oauth2-autoconfigure</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

  2)application.properties

#不需要,暂时写死在代码中,重构时移植到此处即可

  3)主配置类

@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .httpBasic()
            .and()
            .csrf().disable();
    }
    @Bean("authenticationManager")
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

  4)用户认证类

@Component("userDetailsService")
public class MyUserDetailsService implements UserDetailsService{

    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("登录用户名:"+username);
        String  password = passwordEncoder.encode("123456");
        return new User(username,password,true,true,true,true,
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_USER"));
    }
}

  5)认证服务类

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter{

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
        .authenticationManager(authenticationManager)
        .userDetailsService(userDetailsService);
    }
    @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
             .inMemory()//Token保存在内存中
            .withClient("MyProject").secret(passwordEncoder.encode("MyProject_123"))//指明client-id和client-secret
            .accessTokenValiditySeconds(7200)//令牌有效时间,单位秒
            .authorizedGrantTypes("refresh_token","password")//支持刷新令牌、密码模式
            .scopes("all","read","write");//配置权限
    }
}

  说明:

  a)client-secret必须加密,否则在后面测试中,总是弹出让输入用户名、密码。

  b)代码中配置了权限,客户端可以不携带scopes参数,如果携带必须是all、read、write或者其组合。

  6)启动类

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

  3、测试验证

  1)验证默认scope情况获取Token

  技术图片

  技术图片

  2)验证指定scope情况获取Token

  技术图片

  说明:

  a)发送参数是all write,返回scope是all write

  b)发送参数是write read,返回scope是read write

  c)发送除了all read write以外的任何scope值,都返回"Invalid scope",不能用逗号分隔。

  4、给多个应用发送Token

  修改认证服务类中configure方法,如下,模拟给两个应用发送令牌:

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    InMemoryClientDetailsServiceBuilder builder = clients.inMemory();
    
    List<String> list = new ArrayList<String>();
    String app1 = "MyProject,MyProject_123,7200";
    String app2 = "Test,Test123,10";
    list.add(app1);
    list.add(app2);
String client
= ""; String secret = ""; int accessTokenValiditySeconds; for(String str:list) { client = str.split(",")[0]; secret = str.split(",")[1]; accessTokenValiditySeconds = Integer.valueOf(str.split(",")[2]); builder.withClient(client).secret(passwordEncoder.encode(secret))      .accessTokenValiditySeconds(accessTokenValiditySeconds)      .authorizedGrantTypes("refresh_token","password")      .scopes("all","read","write"); } }

  5、使用Redis存储Token

  使用Redis存储Token,当应用重启后,Token不会改变。

  1)引入Redis依赖,并添加配置

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
spring.redis.host = 192.168.7.151
spring.redis.port = 637

  2)配置TokenStore为Redis

@Configuration
public class TokenStoreConfig {

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

  3)修改认证服务类中configure方法,给endpoints指定Token存储方式为Redis

@Autowired
private TokenStore tokenStore;

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
        .tokenStore(tokenStore)
        .authenticationManager(authenticationManager)
        .userDetailsService(userDetailsService);
}

  4)演示,初始时候Redis的key为空,当Rest插件请求一次Token后,Redis中写入了数据。重启应用再访问,Token不改变。

  技术图片

 

 

 

 

 

  

 

使用SpringSecurityOAuth2配置自定义Token实现OAuth2授权示例

标签:bsp   extend   htm   secret   请求   方式   rop   frame   HCL   

原文地址:https://www.cnblogs.com/javasl/p/13068613.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!