springCloud微服务系列——OAuth2+Basic验证

目录

一、简介

二、知识点

@Order

httpSecurity与authorizeRequests设置的区别

三、解决方案


一、简介

    我们希望微服务通过OAuth2+jwt的模式进行验证,但是有些资源我们并不想通过OAuth2+jwt进行验证,比如访问swagger和actuator端点,这些资源我们希望进行Basic验证。

二、知识点

  • @Order

     spring security的验证是通过fliter链进行的,我们实现相应的ConfigurerAdapter就能自定义自己的fliter,我们通过@Order设置它在fliter链中的调用顺序。一般Basic验证应该先与其它验证

  • httpSecurity与authorizeRequests设置的区别

     我们先看如下代码有什么不同

http.requestMatcher(EndpointRequest.toAnyEndpoint())
http.antMatcher(SWAGGER_URL)

http.authorizeRequests().requestMatcher(EndpointRequest.toAnyEndpoint())
http.authorizeRequests().antMatcher(SWAGGER_URL)

      直接在http上定义,表明整个ConfigurerAdapter作用的资源。注意,这里requestMatcher和antMatcher只能传递一个参数。

      在authorizeRequests上定义,表明实际需要控制权限的资源,往往其后需要跟authenticated和permitAll方法。

三、解决方案

     有了以上知识点,解决方案也就很容易想出来了。Basic验证,OAuth2验证服务器,OAuth2资源服务器分别实现一个ConfigurerAdapter,通过在http上定义requestMatcher或antMatcher来进行区分资源。最后用@Order,把Basic验证的fliter设置在前面。

      Basic验证

@Order(1)
@Configuration
@EnableWebSecurity
public class ServerWebSecurityConfig extends WebSecurityConfigurerAdapter {

	private static final String SWAGGER_URL = "/swagger-ui.html";
	
	private static final String REFRESH_URL = "/actuator/refresh";
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		
		 http.requestMatcher(new LuminaryRequestedMatcher())
		 	 .httpBasic()
		     .and()
	         .authorizeRequests()
	         // swagger页面需要添加登录校验
	         .antMatchers(SWAGGER_URL).authenticated()
	         // 监控节点需要添加登录校验
	         .requestMatchers(EndpointRequest.toAnyEndpoint()).authenticated()
	         .and()
	         // 允许刷新服务
	         .csrf().ignoringAntMatchers(REFRESH_URL);
		 
	}
	
	private static class LuminaryRequestedMatcher implements RequestMatcher {
	    public boolean matches(HttpServletRequest request) {
	    	AntPathRequestMatcher swaggerRequestMatcher = new AntPathRequestMatcher(SWAGGER_URL);
	    	EndpointRequestMatcher endpointRequestMatcher = EndpointRequest.toAnyEndpoint();
	        return swaggerRequestMatcher.matches(request) || endpointRequestMatcher.matches(request);
	    }
	}
	
}

        Oauth2验证服务器

@Configuration
public class SsoWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

	@Autowired
	private UserDetailsService userDetailsService;
	
	@Autowired
	SmsCodeAuthenticationSecurityConfiguration smsCodeAuthenticationSecurityConfig;
	
	@Autowired
	ValidateCodeSecurityConfiguration validateCodeSecurityConfiguration;
	
	@Autowired
	protected AuthenticationSuccessHandler defaultAuthenticationSuccessHandler;

	@Autowired
	protected AuthenticationFailureHandler defaultAuthenticationFailureHandler;
	
	@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
	
	@Bean
	@ConditionalOnMissingBean(PasswordEncoder.class)
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
	
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
	}
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// 非basic授权,表单方式
		// 所有请求需要身份认证
		http.formLogin()
			.loginPage(Constants.LOGIN_CONTROLLER)
			.loginProcessingUrl(Constants.DEFAULT_FORM_AUTHENTICATION_URL)
			.successHandler(defaultAuthenticationSuccessHandler)
			.failureHandler(defaultAuthenticationFailureHandler)
			.and()
			.apply(smsCodeAuthenticationSecurityConfig)
			.and()
			.apply(validateCodeSecurityConfiguration)
			.and()
			.authorizeRequests()
			.antMatchers(
					 Constants.LOGIN_CONTROLLER,
					 Constants.IMAGE_CODE_CONTROLLER+"/**",
					 Constants.SMS_CODE_CONTROLLER+"/**",
					 "/swagger-resources/**",
					 "/v2/api-docs",
					 "/webjars/**",
					 "/oauth/check_token").permitAll()
			.anyRequest()
			.authenticated()
			.and()
			.csrf().disable();
	}
	
}

        OAuth2资源服务器

@Configuration
@EnableResourceServer
public class DefaultResourceServerConfiguration extends ResourceServerConfigurerAdapter {

	@Autowired
	SmsCodeAuthenticationSecurityConfiguration smsCodeAuthenticationSecurityConfiguration;
	
	/**
	 * 
	 * 安全验证配置
	 * 
	 */
	@Override
	public void configure(HttpSecurity http) throws Exception {
		http.requestMatcher(new OAuthRequestedMatcher())
			.formLogin()
			.loginPage(Constants.LOGIN_CONTROLLER)
//			.loginProcessingUrl(Constants.DEFAULT_FORM_AUTHENTICATION_URL)
//			.successHandler(defaultAuthenticationSuccessHandler)
//			.failureHandler(defaultAuthenticationFailureHandler)
			.and()
//			.apply(smsCodeAuthenticationSecurityConfig)
//			.and()
			//.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class)
			//.apply(validateCodeSecurityConfig)
			//.and()
			.authorizeRequests()
				 .antMatchers(
						 Constants.LOGIN_CONTROLLER,
						 Constants.IMAGE_CODE_CONTROLLER+"/**",
						 Constants.SMS_CODE_CONTROLLER+"/**",
						 "/oauth/check_token",
						 "/swagger-resources/**",
						 "/v2/api-docs",
						 "/webjars/**",
						 "/oauth/check_token"
//						 securityProperties.getBrowser().getLoginPage(),
//						 Constants.IMAGE_CODE_CONTROLLER,
//						 Constants.SMS_CODE_CONTROLLER
//						 securityProperties.getBrowser().getSession().getInvalidSessionUrl(),
//						 securityProperties.getBrowser().getLogoutUrl()
						 ).permitAll()
				 .anyRequest()
				 .authenticated()
				 .and()
			 .csrf().disable();
	}
	
	private static class OAuthRequestedMatcher implements RequestMatcher {
	    public boolean matches(HttpServletRequest request) {
	        String auth = request.getHeader("Authorization");
	        boolean haveOauth2Token = (auth != null) && auth.startsWith("bearer");
	        boolean haveAccessToken = request.getParameter("access_token")!=null;
	        return haveOauth2Token || haveAccessToken;
	    }
	}
	
}

 

你可能感兴趣的:(spring-cloud)