• springcloud~微服务里的oauth2集成总结


    版本声明

    Springboot,springcloud,spring secutity,spring ouath2都需要有明确的版本声明,对于不同版本的类库,实现上也有很大的区别,不同版本的授权是不能通用的。

    项目定义

    1. 网关服务 gateway
    2. 授权服务 oauth,uaa
    3. 用户服务 system-service
    4. 其它微服务 others-service

    授权流转方式

    1. 用户调用gateway的登陆接口
    2. gateway里进行参数组织,调用oauth的颁发token接口
    3. 用户拿到token之后,带着token去访问资源服务的接口

    版本定义

    springboot+springcloud

     <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.4.RELEASE</version>
            <relativePath/>
    </parent>
    <properties>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
        <spring-cloud-alibaba.version>2.0.2.RELEASE</spring-cloud-alibaba.version>
        <spring-cloud-starter-oauth2.version>2.0.0.RELEASE</spring-cloud-starter-oauth2.version>
        <spring-security-oauth2.version>2.3.3.RELEASE</spring-security-oauth2.version>
        <spring-boot-starter-security.version>2.0.0.RELEASE</spring-boot-starter-security.version>
    </properties>
    <dependencyManagement>
            <dependencies>
                <!--spring cloud 版本-->
                <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>
    

    gateway,oauth,system等服务添加引用

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
                <version>${spring-boot-starter-security.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.security.oauth</groupId>
                <artifactId>spring-security-oauth2</artifactId>
                <version>${spring-security-oauth2.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-oauth2</artifactId>
                <version>${spring-cloud-starter-oauth2.version}</version>
            </dependency>
    

    gateway添加bean

    @EnableWebFluxSecurity
    public class GatewaySecurityConfig {
        @Bean
        SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity serverHttpSecurity)
                throws Exception {
            serverHttpSecurity
                    .csrf().disable();
            serverHttpSecurity.cors();
            return serverHttpSecurity.build();
        }
    }
    
    

    ouath添加bean

    AuthorizationServerConfig继承AuthorizationServerConfigurerAdapter 用来配置客户端详情服务(ClientDetailsService),客户端详情信息在这里进行初始化,你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息。

    ResourceServerConfig它上面添加注解@EnableResourceServer帮我们加入了
    org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter,该filter帮我们从request里解析出access_token并通过org.springframework.security.oauth2.provider.token.DefaultTokenServices根据access_token和认证服务器配置里的TokenStore从redis或者jwt里解析出用户注意认证中心的@EnableResourceServer和别的微服务里的@EnableResourceServer有些不同别的微服务是通过org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices来获取用户的.

    @Configuration
    @EnableResourceServer
    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.requestMatcher(new OAuth2RequestedMatcher()).authorizeRequests()
                    .antMatchers(PermitAllUrl.permitAllUrl()).permitAll() // 放开权限的url
                    .anyRequest().authenticated();
        }
    
        /**
         * 判断来源请求是否包含oauth2授权信息<br>
         * url参数中含有access_token,或者header里有Authorization
         */
        private static class OAuth2RequestedMatcher implements RequestMatcher {
            @Override
            public boolean matches(HttpServletRequest request) {
                // 请求参数中包含access_token参数
                if (request.getParameter(OAuth2AccessToken.ACCESS_TOKEN) != null) {
                    return true;
                }
    
                // 头部的Authorization值以Bearer开头
                String auth = request.getHeader("Authorization");
                if (auth != null) {
                    return auth.startsWith(OAuth2AccessToken.BEARER_TYPE);
                }
    
                return false;
            }
        }
    
    }
    

    SecurityConfig,这个bean主要设置用户获取接口和加密规则

    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        public UserDetailsService userDetailsService;
    
        @Autowired
        private BCryptPasswordEncoder passwordEncoder;
    
        @Value("${pkulaw.token.redis}")
        private Boolean tokenRedis;
    
        @Value("${pkulaw.tokenExpireTime}")
        private Integer tokenExpireTime;
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
        }
    
    
        /**
         * 认证管理
         *
         * @return 认证管理对象
         * @throws Exception 认证异常信息
         */
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
    
        /**
         * http安全配置
         *
         * @param http http安全对象
         * @throws Exception http安全异常信息
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers(PermitAllUrl.permitAllUrl()).permitAll() // 放开权限的url
                    .anyRequest().authenticated().and()
                    .httpBasic().and().csrf().disable();
        }
    

    UserDetailServiceImpl用来获取用户信息,通过通过feign获取system里的接口

    @Service("userDetailsService")
    public class UserDetailServiceImpl implements UserDetailsService {
        @Autowired
        StringRedisTemplate redisTemplate;
        @Autowired
        ObjectMapper objectMapper;
        @Autowired
        private UserClient userClient;
        @Autowired
        private RedisUtil redisUtil;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            String flagKey = "loginFailFlag:" + username;
            String value = redisTemplate.opsForValue().get(flagKey);
            Long timeRest = redisTemplate.getExpire(flagKey, TimeUnit.MINUTES);
            if (StrUtil.isNotBlank(value)) {
                //超过限制次数
                System.out.println("登录错误次数超过限制,请" + timeRest + "分钟后再试");
                throw new PkuLawException("登录错误次数超过限制,请" + timeRest + "分钟后再试");
            }
            User user = userClient.findByUsername(username);
            //持久化到redis
            redisUtil.set(RedisConstant.USER + username, user);
            return new SecurityUserDetails(user);
        }
    }
    

    system添加bean

    system也是资源服务的一种,主要提供用户服务,每个资源服务都有一个ResourceServerConfig的bean,用来规定你的资源开放策略。

    /**
     * 资源服务配置
     */
    @EnableResourceServer
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            super.configure(resources);
        }
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.csrf().disable().exceptionHandling()
                    .authenticationEntryPoint(
                            (request, response, authException) -> response.sendError(
                                HttpServletResponse.SC_UNAUTHORIZED))
                    .and().authorizeRequests()
                    .antMatchers(PermitAllUrl
                        .permitAllUrl("/company/register","/druid/**","/file/view/**","/**/users-anon/**")).permitAll() // 放开权限的url
                    .anyRequest().authenticated()
                    .and().httpBasic()
                    .and().addFilterBefore(new BeforeTokenFilter(), AbstractPreAuthenticatedProcessingFilter.class)
            ;
            http.headers().frameOptions().sameOrigin();
        }
    
    
    
        @Bean
        public BCryptPasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    }
    

    资源服务的配置

    通过在yml里对oauth2的配置,来获取当前oauth里的登录信息,并把登陆状态写到自己服务的HTTP请求里,这个过程是oauth框架帮我们实现的。

    security:
      oauth2:
        resource:
          user-info-uri: http://localhost:6660/pkulaw/oauth/user-me #授权服务的获取当前用户接口,它的返回值是Authentication类型,它会把返回值写到当前服务的请求头里
          prefer-token-info: false
    

    这篇文章主要记录了oauth2搭建的过程。

  • 相关阅读:
    scan design rules
    scan cell
    DFT basics
    测试性分析
    DFT设计绪论
    clock gate cell
    Linux命令
    Multi-voltage和power gating的实现
    Power Gating的设计(架构)
    Power Gating的设计(模块二)
  • 原文地址:https://www.cnblogs.com/lori/p/13398048.html
Copyright © 2020-2023  润新知