当前位置:   article > 正文

Spring Security详解(二)认证之核心配置详解_webinvocationprivilegeevaluator

webinvocationprivilegeevaluator

Spring Security详解(二)认证之核心配置详解

本文链接:https://blog.csdn.net/sinat_29899265/article/details/80736498

2.核心配置解读

2.1 导读

这是Spring Security入门指南中表单登陆的基本配置:

  1. @EnableWebSecurity
  2. @EnableGlobalMethodSecurity(prePostEnabled = true)
  3. ​​​​public class SecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Override
  5. protected void configure(HttpSecurity http) throws Exception {
  6. http
  7. .authorizeRequests()
  8. .antMatchers("/", "/home").permitAll()
  9. .anyRequest().authenticated()
  10. .and()
  11. .formLogin()
  12. .loginPage("/login")
  13. .failureUrl("/error")
  14. .permitAll()
  15. .and()
  16. .logout()
  17. .permitAll();
  18. }
  19. @Autowired
  20. public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  21. auth
  22. .inMemoryAuthentication()
  23. .withUser("user").password("password").roles("USER");
  24. }
  25. }

 

首先解释一下类上面的配置:

  • @EnableWebSecurity:禁用Boot的默认Security配置,配合@Configuration启用自定义配置(需要扩展WebSecurityConfigurerAdapter)
  • @EnableGlobalMethodSecurity(prePostEnabled = true): 启用Security注解,例如最常用的@PreAuthorize。

接下来我们解释一下这样配置的作用:

  • 除了“/”,”/home”(首页),”/login”(登录),”/logout”(注销),之外,其他路径都需要认证。
  • 指定“/login”该路径为登录页面,当未认证的用户尝试访问任何受保护的资源时,都会跳转到“/login”。
  • 指定“/error”为错误页面,当有异常抛出时,跳转到“/error”。
  • 默认指定“/logout”为注销页面。
  • 配置一个内存中的用户认证器,使用admin/admin作为用户名和密码,具有USER角色。

2.2 EnableWebSecurity

    1. @Import({ WebSecurityConfiguration.class,
    2. SpringWebMvcImportSelector.class })
    3. @EnableGlobalAuthentication
    4. @Configuration
    5. public @interface EnableWebSecurity {
    6. boolean debug() default false;
    7. }

     

  • @Import是用于Spring Boot提供的引入外部配置的注解
  • SpringWebMvcImportSelector的作用是判断当前的环境是否包含springmvc,因为spring security可以在非spring环境下使用,为了避免DispatcherServlet的重复配置,所以使用了这个注解来区分。
  • @EnableGlobalAuthentication注解的源码如下:
  1. @Import(AuthenticationConfiguration.class)
  2. @Configuration
  3. public @interface EnableGlobalAuthentication {
  4. }

可以看出,这个注解引入了AuthenticationConfiguration配置。而这个类用来配置认证相关,主要任务就是生成全局的身份认证管理者。AuthenticationManager:

  1. @Configuration
  2. @Import(ObjectPostProcessorConfiguration.class)
  3. public class AuthenticationConfiguration {
  4. private AuthenticationManager authenticationManager;
  5. @Bean
  6. public AuthenticationManagerBuilder authenticationManagerBuilder(
  7. ObjectPostProcessor<Object> objectPostProcessor) {
  8. return new AuthenticationManagerBuilder(objectPostProcessor);
  9. }
  10. public AuthenticationManager getAuthenticationManager() throws Exception {
  11. ...
  12. }
  13. }
  • WebSecurityConfiguration用来配置web安全。在这个类中有一个非常重要的Bean被注册了。
  1. @Configuration
  2. public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
  3. /**
  4. * Creates the Spring Security Filter Chain
  5. * @return
  6. * @throws Exception
  7. */
  8. @Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
  9. public Filter springSecurityFilterChain() throws Exception {
  10. boolean hasConfigurers = webSecurityConfigurers != null
  11. && !webSecurityConfigurers.isEmpty();
  12. if (!hasConfigurers) {
  13. WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor
  14. .postProcess(new WebSecurityConfigurerAdapter() {
  15. });
  16. webSecurity.apply(adapter);
  17. }
  18. return webSecurity.build();
  19. }
  20. }

在未使用springboot之前,在XML配置中,想要启用spring security,需要在web.xml中进行如下配置:

  1. <filter>
  2. <filter-name>springSecurityFilterChain</filter-name>
  3. <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>springSecurityFilterChain</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>

而众所周知,SpringSecurityFilterChain是Spring Security认证的入口。集成Spring Boot集成之后,xml配置被java注解配置取代,也就是在WebSecurityConfiguration中完成了声明springSecurityFilterChain的作用。并且最终交给DelegatingFilterProxy这个代理类,负责拦截请求。

也就是说:@EnableWebSecurity完成的工作便是加载了WebSecurityConfiguration,AuthenticationConfiguration这两个核心配置类,也就此将spring security的职责划分为了配置安全信息,配置认证信息两部分。

2.3 WebSecurityConfigurerAdapter

WebSecurityConfigurerAdapter提供了三个configure方法,是我们需要关心的:

这里写图片描述

可以看出,分别是对AuthenticationManagerBuilder,WebSecurity,HttpSecurity进行个性化的配置。

HttpSecurity

常用配置:

  1. @Configuration
  2. @EnableWebSecurity
  3. public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Override
  5. protected void configure(HttpSecurity http) throws Exception {
  6. http
  7. .authorizeRequests()
  8. .antMatchers("/resources/**", "/signup", "/about").permitAll()
  9. .antMatchers("/admin/**").hasRole("ADMIN")
  10. .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
  11. .anyRequest().authenticated()
  12. .and()
  13. .formLogin()
  14. .usernameParameter("username")
  15. .passwordParameter("password")
  16. .failureForwardUrl("/login?error")
  17. .loginPage("/login")
  18. .permitAll()
  19. .and()
  20. .logout()
  21. .logoutUrl("/logout")
  22. .logoutSuccessUrl("/index")
  23. .permitAll()
  24. .and()
  25. .httpBasic()
  26. .disable();
  27. }
  28. }

上述是一个使用Java Configuration配置HttpSecurity的典型配置,其中http作为根开始配置,每一个and()对应了一个模块的配置(等同于xml配置中的结束标签),并且and()返回了HttpSecurity本身,于是可以连续进行配置。他们配置的含义也非常容易通过变量本身来推测。

  • authorizeRequests()配置路径拦截,表明路径访问所对应的权限,角色,认证信息。
  • formLogin()对应表单认证相关的配置
  • logout()对应了注销相关的配置
  • httpBasic()可以配置basic登录
  • etc

他们分别代表了http请求相关的安全配置,这些配置项无一例外的返回了Configurer类,而所有的http相关配置可以通过查看HttpSecurity的主要方法得知:
这里写图片描述

WebSecurity

  1. public final class WebSecurity {
  2. //全局请求忽略规则配置(比如说静态文件,比如说注册页面)
  3. public IgnoredRequestConfigurer ignoring() {
  4. return ignoredRequestRegistry;
  5. }
  6. //全局http防火墙配置
  7. public WebSecurity httpFirewall(HttpFirewall httpFirewall) {
  8. this.httpFirewall = httpFirewall;
  9. return this;
  10. }
  11. //是否debug配置
  12. public WebSecurity debug(boolean debugEnabled) {
  13. this.debugEnabled = debugEnabled;
  14. return this;
  15. }
  16. //全局SecurityFilterChain配置
  17. public WebSecurity addSecurityFilterChainBuilder(
  18. SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder) {
  19. this.securityFilterChainBuilders.add(securityFilterChainBuilder);
  20. return this;
  21. }
  22. //web权限评估器,默认DefaultWebInvocationPrivilegeEvaluator
  23. public WebSecurity privilegeEvaluator(
  24. WebInvocationPrivilegeEvaluator privilegeEvaluator) {
  25. this.privilegeEvaluator = privilegeEvaluator;
  26. return this;
  27. }
  28. //设置表达式处理器,默认DefaultWebSecurityExpressionHandler
  29. public WebSecurity expressionHandler(
  30. SecurityExpressionHandler<FilterInvocation> expressionHandler) {
  31. Assert.notNull(expressionHandler, "expressionHandler cannot be null");
  32. this.expressionHandler = expressionHandler;
  33. return this;
  34. }
  35. }

一般只有ignoring()配置需要重写:

  1. @Configuration
  2. @EnableWebSecurity
  3. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  4. @Override
  5. public void configure(WebSecurity web) throws Exception {
  6. web
  7. .ignoring()
  8. .antMatchers("/static/**");
  9. }
  10. }

AuthenticationManagerBuilder

主要的方法:

  1. public class AuthenticationManagerBuilder {
  2. //配置父AuthenticationManager
  3. public AuthenticationManagerBuilder parentAuthenticationManager(
  4. AuthenticationManager authenticationManager) {
  5. ...
  6. }
  7. //配置事件发布器
  8. public AuthenticationManagerBuilder authenticationEventPublisher(
  9. AuthenticationEventPublisher eventPublisher) {
  10. ...
  11. }
  12. //认证结束后是否删除密码凭证
  13. public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) {
  14. ...
  15. }
  16. //配置内存用户
  17. public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication()
  18. throws Exception {
  19. return apply(new InMemoryUserDetailsManagerConfigurer<>());
  20. }
  21. //配置数据库用户
  22. public JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcAuthentication()
  23. throws Exception {
  24. return apply(new JdbcUserDetailsManagerConfigurer<>());
  25. }
  26. //配置userDetailService
  27. public <T extends UserDetailsService> DaoAuthenticationConfigurer<AuthenticationManagerBuilder, T> userDetailsService(
  28. T userDetailsService) throws Exception {
  29. ...
  30. }
  31. //配置authenticationProvider
  32. public AuthenticationManagerBuilder authenticationProvider(
  33. AuthenticationProvider authenticationProvider) {
  34. this.authenticationProviders.add(authenticationProvider);
  35. return this;
  36. }
  37. }

具体根据实际情况进行配置,注意:UserDetailService会默认加载DaoAuthenticationProvider

  1. @Override
  2. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  3. auth.userDetailsService(jwtUserDetailsServiceImpl()).passwordEncoder(passwordEncoder());
  4. }

这里还要做一个说明,AuthenticationManagerBuilder有两种配置方式,一种是如上,还有一种是文章开头的配置,如果你的应用只有唯一一个WebSecurityConfigurerAdapter,那么他们之间的差距可以被忽略,从方法名可以看出两者的区别:使用@Autowired注入的AuthenticationManagerBuilder是全局的身份认证器,作用域可以跨越多个WebSecurityConfigurerAdapter,以及影响到基于Method的安全控制;而 protected configure()的方式则类似于一个匿名内部类,它的作用域局限于一个WebSecurityConfigurerAdapter内部。

2.4 配置多个httpSecurity

我们可以配置多个HttpSecurity实例,就像我们可以有多个块. 关键在于对WebSecurityConfigurationAdapter进行多次扩展。例如下面是一个对/api/开头的URL进行的不同的设置。

  1. @EnableWebSecurity
  2. public class MultiHttpSecurityConfig {
  3. @Bean //<1>
  4. public UserDetailsService userDetailsService() throws Exception {
  5. // ensure the passwords are encoded properly
  6. UserBuilder users = User.withDefaultPasswordEncoder();
  7. InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
  8. manager.createUser(users.username("user").password("password").roles("USER").build());
  9. manager.createUser(users.username("admin").password("password").roles("USER","ADMIN").build());
  10. return manager;
  11. }
  12. @Configuration
  13. @Order(1) //<2>
  14. public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
  15. protected void configure(HttpSecurity http) throws Exception {
  16. http
  17. .antMatcher("/api/**") //<3>
  18. .authorizeRequests()
  19. .anyRequest().hasRole("ADMIN")
  20. .and()
  21. .httpBasic();
  22. }
  23. }
  24. @Configuration <4>
  25. public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
  26. @Override
  27. protected void configure(HttpSecurity http) throws Exception {
  28. http
  29. .authorizeRequests()
  30. .anyRequest().authenticated()
  31. .and()
  32. .formLogin();
  33. }
  34. }
  35. }

<1> 配置正常的验证。
<2> 创建一个WebSecurityConfigurerAdapter,包含一个@Order注解,用来指定个哪一个WebSecurityConfigurerAdapter更优先。
<3> http.antMatcher指出,这个HttpSecurity只应用到以/api/开头的URL上。
<4> 创建另外一个WebSecurityConfigurerAdapter实例。用于不以/api/开头的URL,这个配置的顺序在ApiWebSecurityConfigurationAdapter之后,因为他没有指定@Order值为1(没有指定@Order默认会被放到最后).

参考 https://www.cnkirito.moe/spring-security-3/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/534088
推荐阅读
相关标签
  

闽ICP备14008679号