springcloud8

常规权限校验

  • 1.保存用户信息到内存,并保持会话(有状态的会话保持)
  • 2.jsessionId存储浏览器cookie,可能会发生csrf攻击
  • 3.如果用户量大,会话会把内存占满
    • 如果是分布式服务,第一次登陆请求保存在机器1,第二次去查询时访问的是机器2,此时怎么解决?
      • 分布式session
  • 4.在单一架构中,拿到sessionId,就能拿到用户信息(和sessionId绑定)
    • 但是要尽量避免这种有状态的会话,容易发生csrf的跨域攻击
      • 要做到请求跟用户信息无关,oauth2.0标准就出现了

oauth2

四种授权方式

授权码模式
简化模式,基本不用
密码模式
客户端模式
  • 下游系统去认证服务器获取token令牌,token令牌是跟具体客户端相关的,跟用户无关,比如pc、安卓、ios都是不同的
    • 多了一个认证服务器
  • 用户发送的请求,会去认证服务器拿一个token,然后经过zuul网关路由到下游系统,下游系统会去认证服务器校验这个token,验证token是否有效,并且是在有效期内
    • token只是一个用户访问权限的一个字符串,是跟用户信息无关的

微服务权限校验

  • 在zuul是否应该做权限校验?
    • 一般情况不做,因为是没有资源信息的,只是单纯的路由,但是下游系统必须做权限校验
    • 也有只在zuul做权限校验,下游系统不做,但是做了防火墙的白名单,只允许zuul访问,同时也是内网(网络隔离)
      • 如果极端情况,内网被攻破,那么整个系统都是危险的,因为下游系统没有做权限校验
  • 所以zuul什么都不做,下游系统既做token的权限校验,又做防火墙的白名单,这样才是比较安全的权限校验

获取token的方式

客户端模式

  • 以微信小程序为例
    • 1.申请平台认证,AppId,AppSecurityId
    • 2.id passward grant_type,账号、密码、授权方式

密码模式

授权码模式

认证服务器搭建—客户端模式

jar包

  • <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security</groupId>
        <artifactId>spring-security-data</artifactId>
    </dependency>
    

启动类

  • package com.xiangxue.jack;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
    
    @SpringBootApplication
    @EnableEurekaClient
    /*
    * EnableResourceServer注解开启资源服务,因为程序需要对外暴露获取token的API和验证token的API所以该程序也是一个资源服务器
    * */
    @EnableResourceServer
    public class MicroSecurityApplication {
        public static void main(String[] args) {
            SpringApplication.run(MicroSecurityApplication.class,args);
        }
    }
    
    
    • @EnableResourceServer

配置类

  • package com.xiangxue.jack.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.http.HttpMethod;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
    import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
    import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
    import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
    import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
    import org.springframework.security.oauth2.provider.token.TokenStore;
    
    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    
        @Autowired
        private AuthenticationManager authenticationManager;
    
        @Autowired
        private RedisConnectionFactory connectionFactory;
    
        @Autowired
        private UserDetailsService userDetailsService;
    
        // 使用redis保存token
        @Bean
        public TokenStore tokenStore() {
            return new MyRedisTokenStore(connectionFactory);
        }
    
        /*
        * AuthorizationServerEndpointsConfigurer:用来配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)。
        * */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            // authenticationManager是鉴权管理类
            endpoints
                    .authenticationManager(authenticationManager)
                    .userDetailsService(userDetailsService)//若无,refresh_token会有UserDetailsService is required错误
                    .tokenStore(tokenStore()).
                    allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
        }
    
        /*
        * AuthorizationServerSecurityConfigurer 用来配置令牌端点(Token Endpoint)的安全约束
        * */
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            // 允许表单认证
            security.allowFormAuthenticationForClients().tokenKeyAccess("permitAll()")
                    .checkTokenAccess("isAuthenticated()");
        }
    
        /*
    
            ClientDetailsServiceConfigurer:用来配置客户端详情服务(ClientDetailsService),客户端详情信息在这里进行初始化,你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息
        *   1.授权码模式(authorization code)
            2.简化模式(implicit)
            3.密码模式(resource owner password credentials)
            4.客户端模式(client credentials)
        * */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            String finalSecret = "{bcrypt}" + new BCryptPasswordEncoder().encode("123456");
    
            // 代码写死了
            // micro-web和micro-zuul
            clients.
    //                jdbc(dataSource).
                    inMemory().
                    withClient("micro-web")
                    .resourceIds("micro-web")
                    .authorizedGrantTypes("client_credentials", "refresh_token")
                    .scopes("all","read", "write","aa")
                    .authorities("client_credentials")
                    .secret(finalSecret)
                    .accessTokenValiditySeconds(1200)
                    .refreshTokenValiditySeconds(50000)
                    .and()
                    .withClient("micro-zuul")
                    .resourceIds("micro-zuul")
                    .authorizedGrantTypes("password", "refresh_token")
                    .scopes("server")
                    .authorities("password")
                    .secret(finalSecret)
                    .accessTokenValiditySeconds(1200)
                    .refreshTokenValiditySeconds(50000);
        }
    }
    
    
    • @EnableAuthorizationServer
    • 继承AuthorizationServerConfigurerAdapter

另一个配置类

  • package com.xiangxue.jack.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.provisioning.InMemoryUserDetailsManager;
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        // UserDetailsService用来管理用户信息
        @Bean
        @Override
        protected UserDetailsService userDetailsService() {
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
    
            String finalPassword = "{bcrypt}" + bCryptPasswordEncoder.encode("123456");
            InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
            manager.createUser(User.withUsername("jack").password(finalPassword).authorities("USER").build());
            manager.createUser(User.withUsername("admin").password(finalPassword).authorities("USER").build());
    
            return manager;
        }
    
        /*@Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());;
        }*/
    
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            AuthenticationManager manager = super.authenticationManagerBean();
            return manager;
        }
    
        // 使用http鉴权方式
        // "/oauth/**","/actuator/**"这个两个接口时允许访问的
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable();
    //        http.requestMatchers().anyRequest()
    //                .and()
    //                .authorizeRequests()
    //                .antMatchers("/oauth/**").permitAll();
    
            http.authorizeRequests()
                    .antMatchers("/oauth/**","/actuator/**").permitAll()
                    .and()
                    .httpBasic().disable();
        }
    }
    
    
    • @EnableWebSecurity

启动测试

  • 按顺序启动Eureka、MicroConfigServer、MicroSecurity
  • 测试访问:localhost:3030/oauth/token,post请求
    • postman_body_form-data
      • grant_type = client_credentials
      • client_id = micro-web
      • client_secret = 123456
      • scope = all (匹配的字符串,也是在代码中配置的)

总结

  • 客户端模式不常用,控制粒度比较小,只要拿到token就能访问

根据token访问

  • 保留上面的启动,继续启动MicroWebSecurity、MicroZuulSecurity
  • 再次获取token,请求:localhost:7070/web/user/queryUser,get请求
    • Headers中,key=Authorization,value=bearer(获取token中的token类型)+" " + 获取的token
      • 调用失败,去掉链路追踪的properties配置和jar包
      • 调用失败,修改github配置,路由配置错误了
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值