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


      本文记录一下使用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
    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","authorization_code")//支持刷新令牌、密码模式、授权码模式
                   .scopes("all","read","write")//权限有哪些,如果这两配置了该参数,客户端发请求可以不带参数,使用配置的参数
                   .redirectUris("http://127.0.0.1:8080/login");
        }
    }

      说明:

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

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

      c)使用授权码模式,必须配置redirectUris,使用密码模式可以不配置,去掉该语句即可。

      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",不能用逗号分隔。

      3)验证授权码模式

      a)浏览器输入:http://localhost:8080/oauth/authorize?response_type=code&client_id=MyProject&scope=all

      

      b)输入用户名任意,密码123456

      

      c)点击Authorize,浏览器跳转如下地址,授权码为GPLd04

      

      d)获取Token

      

      

      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)
    .refreshTokenValiditySeconds(2592000)      .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不改变。

      

      

  • 相关阅读:
    【今日CS 视觉论文速览】4 Jan 2019
    【今日CS 视觉论文速览】3 Jan 2019
    【今日CS 视觉论文速览】1 Jan 2019
    【机器学习】混淆矩阵及其绘制
    【Vim】批量插入注释符号
    【今日CS 视觉论文速览】31 Dec 2018
    【深度学习风格化/生成艺术】图像融合--毫无违和
    CSDN的一些年度大牛(2018)
    【今日CS 视觉论文速览】 27 Dec 2018
    python与机器视觉(X)打包为exe可执行文件
  • 原文地址:https://www.cnblogs.com/javasl/p/13068613.html
Copyright © 2020-2023  润新知