前言:这个例子只有登录功能,没有前端,也没有控制器(@Controller),使用postman发送请求

在SpringBoot项目的pom.xml中添加下面的依赖

1
2
3
4
<dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-security</artifactid>
</dependency>

此时,这个项目已经被SpringSecurity接管,访问部分资源需要使用系统给定的用户名和密码进行认证,所以需要进行配置那些资源可以访问

新建配置类WebSecurityConfig,继承WebSecurityConfigurerAdapter,实现其中的两个configure方法:

protected void configure(HttpSecurity http)

任何需要防御常见漏洞的端点都可以在此处指定,包括公共漏洞。

上面这句是对源码里的文档注释进行机翻后得到的,可以无视,后面有例子

protected void configure(AuthenticationManagerBuilder auth)

这个方法,源码里的文档注释翻译后我也看不懂,所以不写了

先对第一个方法进行重写,这个可以指定访问那些资源需要什么权限,在没有进行配置的情况下默认是按照下面的方式进行配置的(源码里不是这样的,我只是把默认配置在这里写出来了)

可以看出默认配置中,所有请求都需要认证,所以才会出现上面无法访问的情况

现在需要自己覆盖掉默认的配置,代码如下

现在对登录功能的访问配置已经完成了,接下来进行登录验证的配置,首先要根据username从数据库里获得密码

新建一个类继承UserDetailsService

或让当前已有的UserService继承UserDetailsService

重写loadUserByUsername方法

public UserDetails loadUserByUsername(String username)

根据username定位user

username -标识需要其数据的user的username

返回:完全填充的用户记录(NotNull )

可以看到,它返回的是一个UserDetails对象,不是我们自己定义的User

所以,我们需要对当前的User类进行一些改动,让它继承UserDetails

UserDetails

用于提供核心用户信息。可以将用户的认证信息封装起来

方法:

Collection<? extends GrantedAuthority> getAuthorities();//返回用户的所有权限

String getPassword();//返回用户的密码

String getUsername();//返回用户的用户名

boolean isAccountNonExpired();//账户是否过期

boolean isAccountNonLocked();//账户是否处于未锁定状态

boolean isCredentialsNonExpired();//账户的凭据是否过期

boolean isEnabled();//账户是否已经启用

上述的数据都是需要从数据库中获取,除了usernam和password外的字段如果没有对应的字段,或者只是测试用则可以跳过判断直接返回true

getAuthorities()需要为用户设置权限集合,如果数据库有相应字段,可以根据字段的值为用户动态赋予权限集合,由于数据库中没有这里我们手动赋予所有用户”USER”权限

我们的User已经是UserDetials类型了,现在去实现loadUserByUsername方法

将数据库里获得的结果封装到实现了UserDetials的User类中

现在已经可以获得用户信息了,现在进行验证的配置

重写刚才两个configure方法中的

protected void configure(AuthenticationManagerBuilder auth)方法

这个方法可以配置对用户进行验证的实现方式

这里说一下,数据库里存放密码的时候,不会存放明文密码,而是对密码进行加密的结果,这样可以提高安全性,只有用户知道自己的密码,所以我们忘记密码时一般是让我们重新设置,而不是告诉你之前的密码是什么,因为没有人知道

所以,在重写configure方法之前,我们要对部分已有功能做一些改动,在向数据库中添加用户信息(注册)时就对密码进行加密

在SpringBoot启动类中配置编码器

使用方法:

现在重写configure(AuthenticationManagerBuilder auth)方法

现在已经可以使用postman发送登录请求了,请求的url就是上面设置的/loginProcess

不过这个时候是发送请求不论成功还是失败都是没有响应的,我们需要分别指定登录成功或失败后执行的操作

新建两个类,分别实现下面两个接口:

AuthenticationSuccessHandler//用于处理认证成功的请求的策略

AuthenticationFailureHandler//用于处理认证失败的请求的策略

AuthenticationSuccessHandler中有一个默认方法,会在认证成功后放行当前请求

还有一个需要实现的方法:

前两个参数和Servlet里面那个是同一个东西,第三个是在身份验证过程中创建的身份验证对象。里面有验证信息,包括用户名,密码,和验证是否通过等

重写方法:

将验证信息写入请求体

AuthenticationFailureHandler也可以用类似的方法实现,可以根据需要自己设计重写

将刚才实现的两个接口配置到第一个配置类中

结束!

(总觉得花里胡哨的)