springsecurity知识点

SpringSecurity面试题

001SpringSecurity了解吗?

Spring Security在架构上将认证与授权分离,并提供了扩展点。它是一个轻量级的安全框架,它确保基于Spring的应用程序提供身份验证和授权支持。它与Spring MVC有很好地集成 ,并配备了流行的安全算法实现捆绑在一起。

002SpringSecurity执行流程?

  1. 客户端发起一个请求,进入 Security 过滤器链。

  2. 当到 LogoutFilter 的时候判断是否是登出路径,如果是登出路径则到 logoutHandler ,如果登出成功则到 logoutSuccessHandler 登出成功处理,如果登出失败则由 ExceptionTranslationFilter ;如果不是登出路径则直接进入下一个过滤器。

  3. 当到 UsernamePasswordAuthenticationFilter 的时候判断是否为登录路径,如果是,则进入该过滤器进行登录操作,如果登录失败则到 AuthenticationFailureHandler 登录失败处理器处理,如果登录成功则到 AuthenticationSuccessHandler 登录成功处理器处理,如果不是登录请求则不进入该过滤器。

  4. 当到 FilterSecurityInterceptor 的时候会拿到 uri ,根据 uri 去找对应的鉴权管理器,鉴权管理器做鉴权工作,鉴权成功则到 Controller 层否则到 AccessDeniedHandler 鉴权失败处理器处理。

Spring Security 的执行流程如下:

  1. 用户登录:用户在登录页面输入用户名和密码。
  2. 认证处理器链(AuthenticationManager):Spring Security 会依次调用多个认证处理器(AuthenticationProvider),来对用户进行身份认证,直到有一个认证处理器能够成功认证用户身份为止。
  3. 认证处理器(AuthenticationProvider):认证处理器会根据用户提供的身份信息进行身份认证,如果认证成功,就会生成一个认证成功的令牌(Authentication),否则就会抛出一个认证异常。
  4. 认证成功处理器(AuthenticationSuccessHandler):如果用户的身份认证成功,Spring Security 将调用认证成功处理器来处理成功的事件,例如生成一个认证凭证(Session)。
  5. 认证失败处理器(AuthenticationFailureHandler):如果用户的身份认证失败,Spring Security 将调用认证失败处理器来处理失败的事件,例如记录登录失败日志、锁定用户等。
  6. 访问控制器链(AccessDecisionManager):访问控制器链会根据用户的身份、角色、权限等信息来判断用户是否有权限访问某个资源。如果用户没有权限,访问控制器链将会抛出一个访问拒绝异常(AccessDeniedException)。
  7. 访问拒绝处理器(AccessDeniedHandler):如果用户没有权限访问某个资源,Spring Security 将调用访问拒绝处理器来处理拒绝的事件,例如显示一个访问拒绝页面。
  8. 安全上下文管理器(SecurityContext):安全上下文管理器是一个线程本地的对象,用于存储当前用户的安全上下文信息,例如认证令牌、权限信息等。
  9. 退出处理器(LogoutHandler):如果用户退出登录,Spring Security 将调用退出处理器来处理退出事件,例如清空用户的安全上下文信息、生成一个退出日志等。

总之,Spring Security 是一个非常强大的安全框架,可以帮助我们实现各种复杂的安全需求,例如身份认证、权限管理、访问控制等。了解 Spring Security 的执行流程,可以帮助我们更好地理解 Spring Security 的工作原理,并快速定位和解决安全问题。

003Shiro和SpringSecurity区别?

  1. Shiro比Spring Security更容易使用,也就是实现上简单一些,同时基本的授权认证Shiro也基本够用
  2. Spring Security社区支持度更高,Spring社区的亲儿子,支持力度和更新维护上有优势,同时和Spring这一套的结合较好。
  3. Shiro功能强大、且 简单、灵活。是Apache 下的项目比较可靠,且不跟任何的框架或者容器绑定,可以独立运行。

004SpringSecurity如何解决跨域问题?

SpringSecurity中提供了专业的方式来解决预检请求所面临的问题:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .httpBasic()
                .and()
                // 开启跨域配置
                .cors()
                .configurationSource(corsConfigurationSource())
                .and()
                .csrf().disable();
    }

    CorsConfigurationSource corsConfigurationSource() {
        // 提供CorsConfiguration实例,并配置跨域信息
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));
        corsConfiguration.setAllowedOrigins(Arrays.asList("http://localhost:8081"));
        corsConfiguration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }
}

cors()方法开启了对CorsConfigurer的配置,其最重要的方法就是configure方法:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .httpBasic()
                .and()
                // 开启跨域配置
                .cors()
                .configurationSource(corsConfigurationSource())
                .and()
                .csrf().disable();
    }

    CorsConfigurationSource corsConfigurationSource() {
        // 提供CorsConfiguration实例,并配置跨域信息
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));
        corsConfiguration.setAllowedOrigins(Arrays.asList("http://localhost:8081"));
        corsConfiguration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }
}

拿到CorsFilter之后,调用http.addFilter方法将其添加到spring security过滤器链中,在过滤器链构建之前,会先对所有的过滤器进行排序,排序的依据在FilterOrderRegistration中已经定义好了:

FilterOrderRegistration() {
    Step order = new Step(INITIAL_ORDER, ORDER_STEP);
    put(ChannelProcessingFilter.class, order.next());
    order.next(); // gh-8105
    put(WebAsyncManagerIntegrationFilter.class, order.next());
    put(SecurityContextPersistenceFilter.class, order.next());
    put(HeaderWriterFilter.class, order.next());
    put(CorsFilter.class, order.next());
    put(CsrfFilter.class, order.next());
    put(LogoutFilter.class, order.next());
    // ...
}

可以看到,CorsFilter的位置在HeaderWriterFilter之后,在CsrfFilter之前,这个时候还没到认证过滤器。Spring security根据开发者提供的CorsConfigurationSource对象构建出一个CorsFilter,并将该过滤器置于认证过滤器之前。

005SpringSecurity如何对密码进行加密?

Spring Security 提供了多种加密算法的实现,开箱即用,非常方便。这些加密算法实现类的父类是 PasswordEncoder ,如果你想要自己实现一个加密算法的话,也需要继承 PasswordEncoder。
PasswordEncoder 接口一共也就 3 个必须实现的方法。

public interface PasswordEncoder {

    // 加密也就是对原始密码进行编码
    String encode(CharSequence var1);

    // 比对原始密码和数据库中保存的密码
    boolean matches(CharSequence var1, String var2);

    // 判断加密密码是否需要再次进行加密,默认返回 false
    default boolean upgradeEncoding(String encodedPassword) {
        return false;
    }
}

官方推荐使用基于 bcrypt 强哈希函数的加密算法实现类。

006SpringSecurity如何优雅更换系统使用的加密算法?

推荐的做法是通过 DelegatingPasswordEncoder 兼容多种不同的密码加密方案,以适应不同的业务需求。
DelegatingPasswordEncoder 其实就是一个代理类,并非是一种全新的加密算法,它做的事情就是代理上面提到的加密算法实现类。在 Spring Security 5.0 之后,默认就是基于 DelegatingPasswordEncoder 进行密码加密的。

007SpringSecurity有哪些控制请求访问权限的方法?

● permitAll() :无条件允许任何形式访问,不管你登录还是没有登录。
● anonymous() :允许匿名访问,也就是没有登录才可以访问。
● denyAll() :无条件决绝任何形式的访问。
● authenticated():只允许已认证的用户访问。
● fullyAuthenticated() :只允许已经登录或者通过 remember-me 登录的用户访问。
● hasRole(String) : 只允许指定的角色访问。
● hasAnyRole(String) : 指定一个或者多个角色,满足其一的用户即可访问。
● hasAuthority(String) :只允许具有指定权限的用户访问
● hasAnyAuthority(String) :指定一个或者多个权限,满足其一的用户即可访问。
● hasIpAddress(String) : 只允许指定 ip 的用户访问。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值