您的当前位置:首页正文

Spring Security Web安全性解决方案

2024-11-07 来源:个人技术集锦

1. 简介

Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。
Spring Security 是通过加入自定义过滤器的方式,对访问请求进行认证和鉴权,核心过滤器就是认证过滤器和鉴权过滤器。

用户认证(Authentication)

一般为用户名和密码认证,又称登录验证

用户授权(Authorization)

每个用户对网站的操作权限不同,即分配用户权限

核心

UsernamePasswordAuthenticationFilter 登录认证
(RememberMeAuthenticationFilter,BasicAuthenticationFilter,AnonymousAuthenticationFilter) 其余的认证过滤器
ExceptionTranslationFilter 异常处理
FilterSecurityInterceptor 鉴权拦截处理

2. 认证过程

2.1 认证过程解析

2.1.1 Authentication(用来传递用户信息:用户名 + 密码 + 权限列表等)

2.1.2 UsernamePasswordAuthenticationFilter(账号密码认证过滤器,验证方式由AuthenticationManager 提供)

2.1.3 AuthenticationManager(认证管理器,是发起认证的出发点。提供一个默认实现ProviderManager)

2.1.3.1 ProviderManager(认证提供者管理器,该类中维护了一个认证提供者列表,只要这个列表中的任何一个认证提供者提供的认证方式认证通过,认证就结束。)
2.1.3.1.1 AuthenticationProvider(认证提供者,具体如何认证就看如何实现这个接口。SpringSecurity提供了DaoAuthenticationProvider实现,是使用数据库中数据进行验证)
2.1.3.1.1.1 UserDetailsService(根据用户名获取用户详细信息)

2.1.3.1.1.1.1 UserDetails(用户详细信息)

2.1.4 SecurityContextHolder(SecurityContextHolder 是最基本的对象,它负责存储当前 SecurityContext 信息。SecurityContextHolder默认使用 ThreadLocal 来存储认证信息,意味着这是一种与线程绑定的策略。在Web场景下的使用Spring Security,在用户登录时自动绑定认证信息到当前线程,在用户退出时,自动清除当前线程的认证信息。)

2.1.4.1 SecurityContext(SecurityContext 负责存储认证通过的用户信息(Authentication对象),保存着当前用户是什么,是否已经通过认证,拥有哪些权限等等。)

3. 鉴权过程

4. SpringSecurity 使用

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <scope>compile</scope>
        </dependency>
  1. 重写配置(不重写配置也能使用,SpringSecurity中有许多的默认配置。重写配置是为了能符合我们自己的业务需求。需要重写三个configure方法)
    (1) 资源权限配置(void configure(HttpSecurity http))
    主要功能:
    1. 配置被拦截的资源
    2. 拦截对应的角色权限(即拥有某个权限才能访问)
    3. 定义认证方式:HttpBasic 或 HttpForm
    4. 自定义登录界面,登录请求地址,错误处理方式
    5. 自定义SpringSecurity过滤器
/**
* 资源权限配置(过滤器链)
* 1、配置被拦截的资源
* 2、拦截对应的角色权限(即拥有某个权限才可以访问)
* 3、定义认证方式:httpBasic或者httpForm
* 4、自定义登录界面、登录请求地址、错误处理方式等
* 5、自定义SpringSecurity过滤器
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
    //采用HttpBasic认证
    http.formLogin()
        //自定义登录界面
        .loginPage("/login/toLogin")
        //用户名的参数名
        .usernameParameter("username")
        //密码的参数名
        .passwordParameter("password")
        //登录请求的地址(默认是/login)
        .loginProcessingUrl("/login/doLogin")
        //登录成功后转发到(这里是post请求,因为是“转发”,不适重定向)
        .successForwardUrl("/test/hello")
        //登录失败
        .failureForwardUrl("/login/fail")
        .and()
        .authorizeRequests()
        //对于login请求直接放开
        .antMatchers("/login/toLogin").permitAll()
        //所有请求
        .anyRequest()
        //都需要认证
        .authenticated()
        .and().csrf().disable()
        ;
    }

2022 年 2 月 Spring 推荐使用 Bean 注解的方式来配置,如下:

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((authz) -> authz
                .anyRequest().authenticated()
            )
            .httpBasic(withDefaults());
        return http.build();
    }

(2)自定义身份认证(configure(AuthenticationManagerBuilder auth))

    /**
     * SpringSecurity 5.x之后密码必须编码否则会报空指针
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
      /**
     * 自定义身份认证
     * 该配置类的用于用户的认证
     * 1、提供身份信息(用户名、密码、角色、权限)
     * 2、配置认证信息的存储方式:内存、数据库
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //基于内存的存储方式
        auth.inMemoryAuthentication()
                .withUser("hardy")
                .password(passwordEncoder().encode("123456"))
                .roles("admin");
    }

2022 年 2 月 Spring 推荐以 Bean 的方式来配置,如下:


显示全文