• 网关安全(二)-OAuth2协议简介与认证服务器搭建


    1、OAuth2协议中的角色流程概要介绍

    OAuth2协议主要使用来认证和授权的,我们先来看一下OAuth2协议中的角色

      1.1、用户:真正的人,大家都有可能是某一个服务的用户。

      1.2、客户端应用:Web或手机App,直接跟用户打交道的。通过客户端应用发http请求,访问服务。

      1.3、认证服务器:作用就是认证,验证用户身份发出令牌。

      1.4、资源服务器:在这里代表各个微服务。一个认证服务器可以对应多个资源服务器。

      大概的流程是:用户直接访问客户端应用,客户端首先要去认证服务器认证,验证要访问微服务用户的真实性,认证服务器确认用户身份后,会发出一个代表用户身份的令牌给客户端应用,客户端应用就会拿着令牌去访问资源服务器(我们的微服务),资源服务器会去认证服务器验证这个令牌是谁。

    2、部分角色准备

      2.1、用户,就是我们自己。

      2.2、客户端应用:http请求工具,可以是Restlet Client、Postman等。

      2.3、资源服务器,我们准备两个简单的微服务,一个订单服务,一个价格服务,订单服务调用价格服务获取价格。

        2.3.1、订单服务,端口9080

        2.3.2、价格服务,端口9070

    3、搭建认证服务器

      3.1、项目结构

       3.2、pom.xml导入spring-cloud-starter-oauth2依赖

        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>2.2.0.RELEASE</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Greenwich.SR2</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
    
        <properties>
            <java.version>1.8</java.version>
            <maven.compiler.source>${java.version}</maven.compiler.source>
            <maven.compiler.target>${java.version}</maven.compiler.target>
        </properties>
    
    
        <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>
        </dependencies>

      3.3、OAuth2AuthServerConfig,认证服务器配置

    /**
     * OAuth2认证服务器配置类
     * 需要继承AuthorizationServerConfigurerAdapter类,覆盖里面三个configure方法
     * 并添加@EnableAuthorizationServer注解,指定当前应用做为认证服务器
     *
     * @author caofanqi
     * @date 2020/1/31 18:04
     */
    @Configuration
    @EnableAuthorizationServer
    public class OAuth2AuthServerConfig extends AuthorizationServerConfigurerAdapter {
    
    
        @Resource
        private AuthenticationManager authenticationManager;
    
    
        /**
         * 配置授权服务器的安全性
         * checkTokenAccess:验证令牌需要什么条件,isAuthenticated():需要经过身份认证。
         * 此处的passwordEncoders是为client secrets配置的。
         */
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            security.checkTokenAccess("isAuthenticated()").passwordEncoder(new BCryptPasswordEncoder());
        }
    
        /**
         * 配置客户端服务
         */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients
                    //配置在内存中
                    .inMemory()
                    //客户端应用的用户名
                    .withClient("webApp")
                    //客户端应用加密过的密码
                    .secret(new BCryptPasswordEncoder().encode("123456"))
                    //orderApp可以获取所有的权限集合,用于做ACL的权限控制
                    .scopes("read", "write")
                    //发出去令牌的有效期,单位秒
                    .accessTokenValiditySeconds(3600)
                    //可以访问哪些资源服务器
                    .resourceIds("order-server")
                    //授权的方式
                    .authorizedGrantTypes("password")
                    .and()
                    //订单服务要访问资源服务器验证令牌,所以也需要配置相关信息
                    .withClient("orderService")
                    .secret(new BCryptPasswordEncoder().encode("123456"))
                    .scopes("read", "write")
                    .accessTokenValiditySeconds(3600)
                    .resourceIds("order-server")
                    .authorizedGrantTypes("password");
    
        }
    
        /**
         * 配置授权服务器终端的非安全特征
         * authenticationManager 校验用户信息是否合法
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.authenticationManager(authenticationManager);
        }
    
    }

      3.4、WebSecurityConfig,安全配置

    /**
     * WebSecurity安全配置
     *
     * @author caofanqi
     * @date 2020/1/31 22:48
     */
    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
    
        @Resource
        private UserDetailsService userDetailsService;
    
        @Bean
        public BCryptPasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
    
        /**
         * AuthenticationManagerBuilder可以帮助我们构建出一个AuthenticationManager,需要UserDetailsService和PasswordEncoder
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
        }
    
    
        /**
         * 将AuthenticationManager暴露成Bean
         */
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
    }

      3.5、UserDetailsService

    /**
     * 查询用户信息
     * @author caofanqi
     * @date 2020/2/1 3:41
     */
    @Component
    public class UserDetailsServiceImpl implements UserDetailsService {
    
    
        /**
         *  此处为了简便,没有连接数据库,不管什么用户名,只要密码是123456就会通过验证
         */
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            return User.withUsername(username)
                    .password(new BCryptPasswordEncoder().encode("123456"))
                    .authorities("ROLE_ADMIN").build();
        }
    
    }

      3.6、启动项目,端口9020,看控制台有三个路径,/oauth/token获取token,/oauth/token_key,/oauth/check_token用于校验token

       3.7、测试密码模式获取令牌

        3.7.1、请求路径:http://127.0.0.1:9020/oauth/token

        3.7.2、使用httpBasic添加客户端认证信息

        3.7.3、表单添加用户信息,username(用户名)、password(密码)、grant_type(授权模式)、scope(权限范围)

      3.7.4、返回值,access_token(令牌)、token_type(令牌类型)、expires_in(有效期剩余时间)、scope(权限范围)。

    项目源码:https://github.com/caofanqi/study-security/tree/dev-AuthorizationServer

  • 相关阅读:
    C# Socket 入门2(转)
    C# Socket 入门1(转)
    StructLayout特性(转)
    [转载]U3d常规性能优化技巧
    Python语言系统学习(七)
    Python语言系统学习(五)
    python语言系统学习(六)
    python语言系统学习(四)
    白话经典算法-常见排序算法的实现与性能比较
    最快的内容查找算法-----暴雪的Hash算法
  • 原文地址:https://www.cnblogs.com/caofanqi/p/12248777.html
Copyright © 2020-2023  润新知