Spring Security简单案例


文章目录

  • Spring Security简单案例
  • 一、简介
  • 二、身份认证方式
  • 2.1、加入依赖和编写安全配置类
  • 添加`Spring Security`依赖
  • 编写安全配置类
  • 2.2、 HttpBasic 和HttpForm 认证方式
  • HttpBasic认证方式
  • HttpForm 表单认证方式
  • 三、身份认证实践
  • 3.1、指定登录跳转地址
  • 3.2、用户名和密码的默认名称
  • 3.3、将配置更改为动态配置
  • 3.4、实现成功处理类
  • 3.5、实现失败处理类


一、简介

Spring Security 是基于 Spring 的身份认证(Authentication)和用户授权(Authorization)框架,提供了一套 Web 应用安全性的完整解决方案。其中核心技术使用了 Servlet 过滤器、IOCAOP

  • 身份认证

身份认证指的是用户去访问系统资源时,系统要求验证用户的身份信息,用户身份合法才访问对应资源。常见的身份认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。

  • 用户授权

当身份认证通过后,去访问系统的资源,系统会判断用户是否拥有访问该资源的权限,只允许访问有权限的系统资源,没有权限的资源将无法访问,这个过程叫用户授权。比如 会员管理模块有增删改查功能,有的用户只能进行查询,而有的用户可以进行修改、删除。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

二、身份认证方式

2.1、加入依赖和编写安全配置类

添加Spring Security依赖

<!-- spring security 启动器 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

编写安全配置类

  • 创建 com.sse.security.config.SpringSecurityConfig类并继承 org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter方法

在类上添加注解 @Confifiguration 标识为配置类、 @EnableWebSecurity 启动 SpringSecurity 过滤器链功能。

  • 重写一下两个方法
  • confifigure(AuthenticationManagerBuilder auth) 身份认证管理器
  • 认证信息提供方式(用户名、密码、当前用户的资源权限)
  • 可采用内存存储方式,也可能采用数据库方式等
  • confifigure(HttpSecurity http) 资源权限配置(过滤器链)
  • 拦截的哪一些资源
  • 资源所对应的角色权限
  • 定义认证方式: httpBasichttpForm
  • 定制登录页面、登录请求地址、错误处理方式
  • 自定义 spring security 过滤器等
  • 定义com.sse.security.config.PasswordEncoderConfig类实例化 BCryptPasswordEncoder

BCryptPasswordEncoder类是 PasswordEncoder接口的一个实现类, PasswordEncoder接口有一下几个方法。

NO

方法

描述

1

String encode(CharSequence rawPassword);

用于加密明文

2

boolean matches(CharSequence rawPassword, String encodedPassword);

输入的密码与数据库中的密码对比

3

default boolean upgradeEncoding(String encodedPassword) { return false; }

是否需要编码,一般不需要。

在这里创建一个配置类,将 BCryptPasswordEncoder实例注入容器后,需要使用的时候直接从容器中获取,这样比较方便。代码如下:

@Configuration
public class PasswordEncoderConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 明文+随机盐值加密存储
        return new BCryptPasswordEncoder();
    }
}
  • 明文密码加盐值

加密的最终结果分为两部分,盐值 + MD5(password+盐值), 调用 matches(…) 方法的时候,先从密文中得到盐值,用该盐值加密明文和最终密文作对比。这样可以避免有一个密码被破解, 其他相同的密码的帐户都可以破解.因为通过当前机制相同密码生成的密文都不一样。

加密过程(注册): aaa (盐值) + 123(密码明文) > 生成密文 > 最终结果 盐值.密文:aaa.asdlkf 存入数据库校验过程(登录): aaa (盐值, 数据库中得到) + 123(用户输入密码)> 生成密文 aaa.asdlkf,与数据库对比一致密码正确。

2.2、 HttpBasic 和HttpForm 认证方式

HttpBasic认证方式

这种认证方式,会在浏览器的上方弹出登录窗口,这样不是很美观。详细配置如下:

/**
 * 认证管理器:
 * 1、认证信息提供方式(用户名、密码、当前用户的资源权限)
 * 2、可采用内存存储方式,也可能采用数据库方式等
 * @param auth
 * @throws Exception
 */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    // 数据库存储的密码必须是加密后的,不然会报错:There is no PasswordEncoder mapped for the id "null"
    String password = passwordEncoder.encode("1234");
    log.info("加密之后存储的密码:" + password);
    // 设置用户名和角色
    auth.inMemoryAuthentication().withUser("admin")
        .password(password).authorities("ADMIN");
}

/**
 * 资源权限配置(过滤器链):
 * 1、被拦截的资源
 * 2、资源所对应的角色权限
 * 3、定义认证方式:httpBasic 、httpForm
 * 4、定制登录页面、登录请求地址、错误处理方式
 * 5、自定义 spring security 过滤器
 * @param http
 * @throws Exception
 */
@Override
protected void configure(HttpSecurity http) throws Exception {
    // 采用 httpBasic认证方式
    http.httpBasic()
        // 表单登录方式
        .and()
        // 认证请求
        .authorizeRequests()
        .anyRequest()
        //所有访问该应用的http请求都要通过身份认证才可以访问
        .authenticated()
        ; // 注意不要少了分号
}

sse-security-web工程下创建 MainController类,认证通过就访问这里。

Spring Security介绍 spring security例子_spring

启动后在浏览器访问:http://localhost:8080/index

Spring Security介绍 spring security例子_Spring Security介绍_02

输入用户名:admin和密码:1234,就可以访问到资源。

HttpForm 表单认证方式

http.httpBasic()替换成 http.formLogin()就行了。

Spring Security介绍 spring security例子_用户名_03

启动后在浏览器访问:http://localhost:8080/index,访问路径会自动跳转到login路径,验证通过后又跳转到当初访问的路径。

Spring Security介绍 spring security例子_Spring Security介绍_04

当前版本号:bd91e527929e4f42797df1ab0ba0f1657734f988

三、身份认证实践

3.1、指定登录跳转地址

直接在资源配置类中添加 loginPage(String loginPage)方法指定就可以了,但是需要注意:现在拦截的是所有全部请求,自定义一个登录请求,需要将这个地址设置为不认证也可以访问。如果不这样设置,页面会提示“重定向次数过多”。因为登录的时候会访问“login"l路径,设置新的登录地址后,一直来访问新的这个地址,但是这个地址必须登录才可以访问,所以一直循环这样调用,就会出现重定向次数过多。设置如下:

Spring Security介绍 spring security例子_用户名_05

访问登录页面的时候,需要跳转到“login/page"地址,但是没有这个登录也。所以需要在创建这个路径,否则会提示404找不到这个路径。

Spring Security介绍 spring security例子_身份认证_06

还可以放行所有静态资源,如果是那些前后端没有分离的项目,所有前端的静态资源都保存在代码中,如果不放行这些静态资源,没有登录时不能访问的。配置如下:

Spring Security介绍 spring security例子_用户名_07

3.2、用户名和密码的默认名称

有的时候,前端提交的用户名和密码的名称,就是根据名称获取前端的用户名和密码的这个名称。如果不喜欢使用默认的,也是可以更改。

Spring Security介绍 spring security例子_身份认证_08

默认的用户名变量名:username,密码变量名:password

可以通过 usernameParameter(String usernameParameter)passwordParameter(String passwordParameter)方法更改。

Spring Security介绍 spring security例子_用户名_09

Spring Security介绍 spring security例子_spring_10

当前版本号:04d73e4ae03a52af9d16d087e3ae2c968965fa95

3.3、将配置更改为动态配置

将登录地址、密码和用户名称这些值设置为动态配置的,在代码中去配置不是很理想。直接在yml或者properties文件中动态配置比较乐观,现在就更改为这样的配置方式。

创建 com.sse.security.properites.SecurityProperties配置文件映射类,在创建 com.sse.security.properites.AuthenticationProperties保存配置信息类。

Spring Security介绍 spring security例子_身份认证_11

在配置文件中就可以直接调用配置类,获取配置信息就行了。

Spring Security介绍 spring security例子_spring_12

3.4、实现成功处理类

有些程序登录会做一些非同寻常的操作,那么可以创建一个登录成功处理类。主要关注的是 org.springframework.security.web.authentication.AuthenticationSuccessHandler这个接口,但是我为了能够实现返回JSON格式数据还是重定向地址,我就实现这个接口的实现类,SavedRequestAwareAuthenticationSuccessHandler

创建 CustomAuthenticationSuccessHandler类,并继承 SavedRequestAwareAuthenticationSuccessHandler类,实现 onAuthenticationSuccess方法,在这个方法里面就可以做一些登录成功需要处理的数据。

Spring Security介绍 spring security例子_身份认证_13

SpringSecurityConfig中配置 successHandler并指定成功处理类就可以生效了。

Spring Security介绍 spring security例子_用户名_14

判断是返回JSON格式数据还是重定向地址呢?我们直接在配置文件中就可以指定了。

Spring Security介绍 spring security例子_身份认证_15

3.5、实现失败处理类

实现效果和成功处理类差不多,只是关注的接口不一样。主要关注 org.springframework.security.web.authentication.AuthenticationFailureHandler接口,为了方便我就实现该接口的实现类 SimpleUrlAuthenticationFailureHandler,并重写 onAuthenticationFailure方法。

Spring Security介绍 spring security例子_Spring Security介绍_16

SpringSecurityConfig中配置failureHandler方法指定失败处理类就行了。

Spring Security介绍 spring security例子_身份认证_17

全部配置文件如下:

sse:
  security:
    authentication:
      loginPage: /login/page # 响应认证(登录)页面的URL
      loginProcessingUrl: /login/form # 登录表单提交处理的url
      usernameParameter: name # 登录表单提交的用户名的属性名
      passwordParameter: pwd  # 登录表单提交的密码的属性名
      loginType: JSON
      staticPaths: # 静态资源 "/dist/**", "/modules/**", "/plugins/**"
        - /dist/**
        - /modules/**
        - /plugins/**