• 在 Spring Boot 中使用 OAuth 2


    什么是 OAuth 2

    OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。

    OAuth 2.0 是 OAuth 协议的下一版本,但不向后兼容 OAuth 1.0。

    OAuth 2.0 关注客户端开发者的简易性,同时为 Web 应用,桌面应用和手机,和起居室设备提供专门的认证流程。2012 年 10 月,OAuth 2.0 协议正式发布为 RFC 6749.

    参考资源

    1、理解OAuth 2.0 - 阮一峰的网络日志

    2、OAuth 2.0 教程

    3、OAuth 2.0 官网

    在 Spring Boot 中使用 OAuth 2

    Spring Boot 中的 OAuth2 协议是在 Spring Security 的基础上实现的。

    令牌存储在 Redis 中,redis 具有过期功能,很适合存储令牌。

    准备工作

    所需依赖:

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

    application.properties 配置文件:

    # 使用 redis 存储令牌
    # redis 基本配置
    spring.redis.host=146.56.200.244
    spring.redis.password=Test@123456
    spring.redis.port=6379
    spring.redis.database=0
    

    三大配置类

    授权服务配置类:AuthorizationServerConfig

    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
        /**
         * 使用 password 登录模式
         * 适用于前后端分离
         */
        @Autowired
        AuthenticationManager authenticationManager;
    
        @Autowired
        RedisConnectionFactory redisConnectionFactory;
    
        @Autowired
        UserDetailsService userDetailsService;
    
        @Bean
        PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                    // 设置认证模式为 password
                    .withClient("password")
                    // 设置授权模式为 password 和 refresh_token
                    // refresh_token 为 Spring Boot 中特有的授权模式
                    .authorizedGrantTypes("password", "refresh_token")
                    // token 的过期时间
                    .accessTokenValiditySeconds(1800)
                    // 设置资源 id,也就是资源的名字
                    .resourceIds("rid")
                    .scopes("all")
                    .secret("$2a$10$3exePEMS2hwNVXzg3NRPVurMaA/ksEu5UGe6.cSctS3J7l6RsIarS");
        }
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory))
                    .authenticationManager(authenticationManager)
                    .userDetailsService(userDetailsService);
        }
    
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            security.allowFormAuthenticationForClients();
        }
    }
    
    

    资源服务配置类:ResourceServerConfig:

    @Configuration
    @EnableResourceServer
    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            resources.resourceId("rid").stateless(true);
        }
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().antMatchers("/admin/**").hasRole("user")
                    .anyRequest().authenticated();
        }
    }
    

    Security 配置类:SecurityConfig

    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        @Bean
        protected AuthenticationManager authenticationManager() throws Exception {
            return super.authenticationManager();
        }
    
        @Override
        @Bean
        protected UserDetailsService userDetailsService() {
            return super.userDetailsService();
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                    .withUser("you").password("$2a$10$3exePEMS2hwNVXzg3NRPVurMaA/ksEu5UGe6.cSctS3J7l6RsIarS").roles("admin")
                    .and()
                    .withUser("fanqie").password("$2a$10$3exePEMS2hwNVXzg3NRPVurMaA/ksEu5UGe6.cSctS3J7l6RsIarS").roles("user");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.antMatcher("/oauth/**")
                    .authorizeRequests().antMatchers("/oauth/**").permitAll()
                    .and().csrf().disable();
        }
    }
    

    控制类:HelloController

    @RestController
    public class HelloController {
    
        @GetMapping("/admin/hello")
        public String admin(){
            return "hello admin!";
        }
    
        @GetMapping("/user/hello")
        public String user(){
            return "hello user!";
        }
    
        @GetMapping("/hello")
        public String hello(){
            return "hello!";
        }
    
    }
    

    注,SecurityConfig 中的 password 和 AuthorizationServerConfig 中的 secret 是同一个密码。

    这个密码是明文 123 通过 BCryptPasswordEncoder 加密后的效果,

    在测试类中获取加密后的密码:

    @SpringBootTest
    class Oauth2ApplicationTests {
    
        @Test
        void contextLoads() {
            System.out.println(new BCryptPasswordEncoder().encode("123"));
        }
    }
    

    如下图:

    使用 postman 测试

    如下图

    请求结果如下:

    再将获取到的 token 用于 get 请求,效果如下:

    每天学习一点点,每天进步一点点。

  • 相关阅读:
    python 循环的概念
    python 字典的基本操作
    短路表达式
    快捷键myeclipse
    nginx静态文件访问
    安装mysql
    安装mongodb
    安装tomcat
    安装jdk8
    安装node和pm2
  • 原文地址:https://www.cnblogs.com/youcoding/p/13941387.html
Copyright © 2020-2023  润新知