zoukankan      html  css  js  c++  java
  • springcloudsecurity+oauth+redis(jdbc)+mybatisplus实现授权认证+资源认证(基于授权码模式)

    springcloudsecurity+oauth+redis+mybatisplus实现授权认证(基于授权码模式)
    理解OAuth 2.0:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
    1.技术栈;springboot+springcloudsecurity+mybatisplus

    交互过程

    oAuth 在 “客户端” 与 “服务提供商” 之间,设置了一个授权层(authorization layer)。“客户端” 不能直接登录 “服务提供商”,只能登录授权层,以此将用户与客户端区分开来。“客户端” 登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。“客户端” 登录授权层以后,“服务提供商” 根据令牌的权限范围和有效期,向 “客户端” 开放用户储存的资料
    在这里插入图片描述

    认证服务器

    1.AuthorizationServerConfiguration.java

    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
    
        @Autowired
        private UserDetailsServiceImpl userDetailsService;
        @Autowired
        private DataSource dataSource;
        @Autowired
        private AuthenticationManager authenticationManager;
        @Autowired
        private RedisConnectionFactory redisConnectionFactory;
    
       /* @Bean
          public TokenStore tokenStore() {
              // 基于 JDBC 实现,令牌保存到数据库
              return new JdbcTokenStore(dataSource);
          }*/
        //令牌保存到Redis*/
        @Bean
        public TokenStore tokenStore() {
            RedisTokenStore redisToken = new RedisTokenStore(redisConnectionFactory);
            return redisToken;
        }
        @Bean
        public ClientDetailsService jdbcClientDetails() {
            // 基于 JDBC 实现,需要事先在数据库配置客户端信息
            return new JdbcClientDetailsService(dataSource);
        }
    
        /**
         * 在此处定义认证管理,即系统或者集群中的用户以及 Token的存儲方式, 定义授权、token终端、token服务
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            // 自定义token生成方式,增加用户登录名等信息
            TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
            tokenEnhancerChain.setTokenEnhancers(Arrays.asList(new MyTokenEnhancer()));
            //通过注入authenticationManager 会自动开启password grants
            // 设置令牌
            endpoints
                .authenticationManager(authenticationManager)
                .tokenStore(tokenStore()).tokenEnhancer(tokenEnhancerChain)
                .userDetailsService(userDetailsService)
                .exceptionTranslator(e -> {
                    if (e instanceof OAuth2Exception) {
                        OAuth2Exception oAuth2Exception = (OAuth2Exception) e;
                        return ResponseEntity
                            .status(HttpStatus.UNAUTHORIZED)
                            .body(new CustomOauthException(oAuth2Exception.getMessage()));
                    } else {
                        throw e;
                    }
                });
        }
    
        /**
         * 支持刷新token
         *
         * @return DefaultTokenServices
         */
        @Primary
        @Bean
        public AuthorizationServerTokenServices tokenServices() {
            DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
            defaultTokenServices.setAccessTokenValiditySeconds(60000);
            defaultTokenServices.setRefreshTokenValiditySeconds(604800);
            defaultTokenServices.setSupportRefreshToken(true);
            defaultTokenServices.setReuseRefreshToken(false);
            defaultTokenServices.setTokenStore(tokenStore());
            return defaultTokenServices;
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            // 读取客户端配置
            clients.withClientDetails(jdbcClientDetails());
        }
        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    
            //允许表单认证
            oauthServer.allowFormAuthenticationForClients();
    
            //允许 check_token 访问
            oauthServer.checkTokenAccess("permitAll()");
        }
    
    

    2.WebSecurityConfiguration.java

    
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)//全局方法拦截
    public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private UserDetailsServiceImpl userDetailsService;
    
        @Bean
        public BCryptPasswordEncoder passwordEncoder() {
            // 设置默认的加密方式
            return new BCryptPasswordEncoder();
        }
    
       @Bean
        public DaoAuthenticationProvider authProvider() {
            final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
            authProvider.setUserDetailsService(userDetailsService);
            authProvider.setPasswordEncoder(passwordEncoder());
            return authProvider;
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            // 使用自定义认证与授权
            auth
                .authenticationProvider(authProvider())
                .userDetailsService(userDetailsService())
                .passwordEncoder(passwordEncoder());
        }
        @Override
        public void configure(WebSecurity web) throws Exception {
            // 将 check_token 暴露出去,否则资源服务器访问时报 403 错误
            web.ignoring().antMatchers("/oauth/check_token");
        }
    
    
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
        /**
         * 通过HttpSecurity实现Security的自定义过滤配置
         * @param http
         * @throws Exception
         */
        @Override
        public void configure(HttpSecurity http) throws Exception {
    
            http.csrf().disable();
            http
                .requestMatchers().antMatchers("/oauth/**","/login/**","/logout/**")
                .and()
                .authorizeRequests()
                .antMatchers("/oauth/**").authenticated()
                .and()
                .formLogin().permitAll(); //新增login form支持用户登录及授权
        }
    }
    

    3.UserDetailsServiceImpl.java

    @Service
    public class UserDetailsServiceImpl implements UserDetailsService {
    
        @Autowired
        private TbPermissionService tbPermissionService;
        @Autowired
        private TbUserService tbUserService;
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            TbUser tbUser = tbUserService.queryTbUserByUserName(username);
            List<GrantedAuthority> grantedAuthorities = new ArrayList();
            if (StringUtils.isEmpty(tbUser)) {
                throw new UsernameNotFoundException("很抱歉,找不到用户名为" + username + "的用户!");
            }
    
            if (tbUser != null) {
                List<TbPermission> tbPermissions = tbPermissionService
                    .queryPermissionByUserId(tbUser.getId());
                tbPermissions.forEach(tbPermission -> {
                    if (tbPermission != null && tbPermission.getEnname() != null) {
                        GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(tbPermission.getEnname());
                        grantedAuthorities.add(grantedAuthority);
                    }
                });
            }
            /**
             * 若只是认证,要去掉grantedAuthorities换成 Collections.emptyList()
             * 若是要授权,要加上
             */
            CustomUserPrincipal userDetail = new CustomUserPrincipal(tbUser.getUsername(), tbUser.getPassword(), grantedAuthorities);
            userDetail.setTbUser(tbUser);
            return userDetail;
        }
    

    资源服务器

    4.ResourceServerConfiguration.java

    @Configuration
    @EnableResourceServer
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
    public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    
    
        @Autowired
        private RedisConnectionFactory redisConnectionFactory;
    
    
        /*@Autowired
        private DataSource dataSource;
         @Bean
          public TokenStore tokenStore() {
            return new JdbcTokenStore(dataSource);
          }*/
        //
        @Bean
        public TokenStore tokenStore() {
            return new RedisTokenStore(redisConnectionFactory);
        }
    
        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            //resourceId 推荐每个 受保护的资源都提供一下 ,可以供 auth服务对资源进行一个认证
            resources.resourceId("ls_resource").tokenStore(tokenStore());
        }
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .exceptionHandling()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 以下为配置所需保护的资源路径及权限,需要与认证服务器配置的授权部分对应
                .antMatchers("/contents").hasAuthority("SystemContent")
                .antMatchers("/view/**").hasAuthority("SystemContentView")
                .antMatchers("/insert/**").hasAuthority("SystemContentInsert")
                .antMatchers("/update/**").hasAuthority("SystemContentUpdate")
                .antMatchers("/delete/**").hasAuthority("SystemContentDelete");
        }
    }
    

    5.localhost:8080/oauth/authorize?client_id=client&response_type=code获取code
    用户名:admin 密码:123456
    在这里插入图片描述

    6.获取token
    在这里插入图片描述
    7.访问资源
    在这里插入图片描述
    8.其他代码请见GitHub:https://github.com/smileLs66/springcloud/tree/master/auth-oauth2
    参考:
    https://www.funtl.com/zh/guide/Spring-Security-oAuth2.html
    https://www.cnblogs.com/cjsblog/p/10548022.html
    阮一峰的jwt入门教程:http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
    阮一峰理解OAuth2.0: https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

  • 相关阅读:
    169. Majority Element
    283. Move Zeroes
    1331. Rank Transform of an Array
    566. Reshape the Matrix
    985. Sum of Even Numbers After Queries
    1185. Day of the Week
    867. Transpose Matrix
    1217. Play with Chips
    766. Toeplitz Matrix
    1413. Minimum Value to Get Positive Step by Step Sum
  • 原文地址:https://www.cnblogs.com/szls-666/p/12494175.html
Copyright © 2011-2022 走看看