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

  • 相关阅读:
    Stone Game, Why are you always there? HDU
    SG函数
    A New Stone Game POJ
    卡特兰数
    找单词 HDU
    排列组合 HDU
    Harry And Magic Box HDU
    GCD and LCM HDU
    Co-prime HDU
    线段树——F
  • 原文地址:https://www.cnblogs.com/szls-666/p/12494175.html
Copyright © 2011-2022 走看看