• SpringSecurity的OAuth2的授权服务器配置


    OAUTH2概念里有资源服务器与授权服务器
    先看授权服务的配置
    通常,我们会写一个AuthorizationServerConfiguration类继承自AuthorizationServerConfigurerAdapter,并且在类上加@Configuration注解

    • 授权服务器的配置
    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 其中@EnableAuthorizationServer是开启授权服务器,这是一个复合注解,利用@Import引入了AuthorizationServerSecurityConfiguration类,而该类继承了WebSecurityConfigurerAdapter类,这个类很熟悉,是前一篇文章说的Security配置入口
    public class AuthorizationServerSecurityConfiguration extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity http) throws Exception {
    		AuthorizationServerSecurityConfigurer configurer = new AuthorizationServerSecurityConfigurer();
    		FrameworkEndpointHandlerMapping handlerMapping = endpoints.oauth2EndpointHandlerMapping();
    		http.setSharedObject(FrameworkEndpointHandlerMapping.class, handlerMapping);
            // 这里开放了配置AuthorizationServerSecurityConfigurer的入口
    		configure(configurer);
            // 将AuhtorizationServerSecurityConfigurer应用到httpSecurity,通过这种方式开放了httpSecurity部分配置给用户
    		http.apply(configurer);
    		String tokenEndpointPath = handlerMapping.getServletPath("/oauth/token");
    		String tokenKeyPath = handlerMapping.getServletPath("/oauth/token_key");
    		String checkTokenPath = handlerMapping.getServletPath("/oauth/check_token");
    		if (!endpoints.getEndpointsConfigurer().isUserDetailsServiceOverride()) {
    			UserDetailsService userDetailsService = http.getSharedObject(UserDetailsService.class);
    			endpoints.getEndpointsConfigurer().userDetailsService(userDetailsService);
    		}
    		// @formatter:off
    		http
            	.authorizeRequests()
                	.antMatchers(tokenEndpointPath).fullyAuthenticated()
                	.antMatchers(tokenKeyPath).access(configurer.getTokenKeyAccess())
                	.antMatchers(checkTokenPath).access(configurer.getCheckTokenAccess())
            .and()
            //之前文章说过,HttpSecurity最后会变成一个Filter
            // 这里配置RequestMatcher,就意味只有这些url会匹配这个Filter
            	.requestMatchers()
                	.antMatchers(tokenEndpointPath, tokenKeyPath, checkTokenPath)
            .and()
            	.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
    		// @formatter:on
    		http.setSharedObject(ClientDetailsService.class, clientDetailsService);
    	}
        
        protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    		for (AuthorizationServerConfigurer configurer : configurers) {
    			configurer.configure(oauthServer);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    可以看到,OAUTH2的授权服务器过滤器实现,匹配了几个url,分配至/oauth/token; /oauth/token_key;/oauth/check_token;暴露给用户可以配置的为AuthorizationServerSecurityConfigurer

    public final class AuthorizationServerSecurityConfigurer extends
    		SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
    
        // 配置身份信息异常的处理器
    	private AuthenticationEntryPoint authenticationEntryPoint;
    
        // 配置拒绝访问的处理器
    	private AccessDeniedHandler accessDeniedHandler = new OAuth2AccessDeniedHandler();
    
        // 配置client scret的密码编码策略
    	private PasswordEncoder passwordEncoder; // for client secrets
    
        // WWW-Authenticate头使用realm字段字符串提示为了访问指定Url所需要的保护策略
        // WWW-Authenticate  realm=
    	private String realm = "oauth2/client";
    
        // 允许client/scret验证以表单方式提交
    	private boolean allowFormAuthenticationForClients = false;
    
        // /oauth/token_key的访问策略,/oauth/token_key暴露token的签名算法,适用于JWT的时候
    	private String tokenKeyAccess = "denyAll()";
        
        // /oauth/check_token的访问策略
    	private String checkTokenAccess = "denyAll()";
        // 设置sslOnly
    	private boolean sslOnly = false;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 分析完了EnableAuthorizationServer 注解,接着分析继承的AuthorizationServerConfigurerAdapter类,该类实现了AuthorizationServerConfigurer接口,这里很重要,说明我们自定义的的AuthorizationServerConfiguration是一个AuthorizationServerConfigurer类型的bean。在AuthorizationServerSecurityConfiguration类中就使用AuthorizationServerConfigurer的bean去配置AuthorizationServerConfigurerClientDetailsServiceConfigurer
    public class AuthorizationServerSecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Autowired
    	public void configure(ClientDetailsServiceConfigurer clientDetails) throws Exception {
    		for (AuthorizationServerConfigurer configurer : configurers) {
    			configurer.configure(clientDetails);
    		}
    	}
        
        protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    		for (AuthorizationServerConfigurer configurer : configurers) {
    			configurer.configure(oauthServer);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    如上代码所示,分别是使用自定义配置类去配置ClientDetailsServiceConfigurer(配置clientDetailsService)和AuthorizationServerSecurityConfigurer(最后会被应用进HttpSecurity);AuthorizationServerConfigurer接口还有一个定义是

    /**
    Configure the non-security features of the Authorization Server endpoints, like token store, 
    token customizations, user approvals and grant types. You shouldn't need to do anything by default, 
    unless you need password grants, in which case you need to provide an AuthenticationManager.
    Params:
    endpoints – the endpoints configurer
    */
    void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    它是用来配置AuthorizationServerEndpointsConfigurer的,即这里是用来配置端点非访问安全相关的,比如底层tokenStore,tokenService;认证类型之类的;后续的文章会分析这些类都是用来干嘛的;

    • 总结

    自定义的授权服务器配置类,配置三个方面的,一个是AuthorizationServerSecurityConfigurer,这些最终是会应用到HttpSecurity里的,相当于OAUTH2对HttpSecurity配置进行了权限收缩;另一个是ClientDetailsServiceConfigurer,这个是配置ClientDetailsServcie的,每个访问Oauth授权服务器的,都需要一个client身份,就是用这个ClientDetailsService去进行的Client身份认证;最后一个是AuthorizationServerEndpointsConfigurer,这个配置的是授权服务器底层的实现逻辑,比如token如何存储,用户信息如何获取等非接口访问安全的内容;

  • 相关阅读:
    SpringBoot-属性绑定和bean属性校验
    2022山东健博会,中国大健康产业展,产后健康展,婴儿护理展
    nginx+HTTPS证书
    FPGA入门学习(一) - 第一个FPGA工程
    基于ChatGPT的知识图谱构建
    C语言编程用递归法求
    使用本地自签名证书为 React 项目启用 https 支持
    [Mac软件]Adobe Illustrator 2024 28.3 intel/M1/M2/M3矢量图制作软件
    NDSS 2022 EMS: History-Driven Mutation for Coverage-based Fuzzing
    程序员都应该懂Kubernetes的基本概念和关键组件是什么吗?
  • 原文地址:https://blog.csdn.net/Xjzzon/article/details/126436523