> 文档中心 > SpringBoot 整合 SpringSecurity——入门

SpringBoot 整合 SpringSecurity——入门


SpringBoot 整合 SpringSecurity——入门

0、 环境搭建

新建一个 SpringBoot 项目

  1. 导入依赖:

    <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-security</artifactId></dependency><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId></dependency><dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <optional>true</optional></dependency><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-test</artifactId>    <scope>test</scope></dependency><dependency>    <groupId>org.springframework.security</groupId>    <artifactId>spring-security-test</artifactId>    <scope>test</scope></dependency>
  2. 在 static 包下新建一个 index.html

    <html lang="en">    <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title>    </head>    <body> <h1>首页</h1>    </body></html>
  3. 启动工程

    在控制台得到一串字符串

    Using generated security password: fa3865d2-b254-4d23-b43f-91cc55a3b4c6

    此为 SpringSecurity 自动生成的登录页面的密码

  4. 运行效果
    在这里插入图片描述

    在这里插入图片描述

1、Spring Security 原理

Spring Security本质是一个过滤器链有很多过滤器

  • FilterSecurityInterceptor :是一个方法级的权限过滤器,基本位于过滤链的最底部
  • ExceptionTranslationFilter :是个异常过滤器,用来处理在认证授权过程中轮出的异常
  • UsernamePesswordAuthenticationFilter : 对/login的POST请求做拦截,校验表单中用户名,密码。

1.1、权限管理中的相关概念

  • 主体

    英文单词:principal

    使用系统的用户或设备或从其他系统远程登录的用户等等。简单说就是谁使用系统谁就是主体。

  • 认证

    英文单词:authentication

    权限管理系统确认一个主体的身份,允许主体进入系统。简单说就是“主体”证明自己是谁。

    笼统的认为就是以前所做的登录操作。

  • 授权

    英文单词:authorization

    将操作系统的“权力”“授予”“主体”,这样主体就具备了操作系统中特定功能的能力。

    所以简单来说,授权就是给用户分配权限。

2、UserDetails

package org.springframework.security.core.userdetails;import java.io.Serializable;import java.util.Collection;import org.springframework.security.core.Authentication;import org.springframework.security.core.GrantedAuthority;/** * Provides core user information. * * 

* Implementations are not used directly by Spring Security for security purposes. They * simply store user information which is later encapsulated into {@link Authentication} * objects. This allows non-security related user information (such as email addresses, * telephone numbers etc) to be stored in a convenient location. *

* Concrete implementations must take particular care to ensure the non-null contract * detailed for each method is enforced. See * {@link org.springframework.security.core.userdetails.User} for a reference * implementation (which you might like to extend or use in your code). * * @author Ben Alex * @see UserDetailsService * @see UserCache */public interface UserDetails extends Serializable {// 表示获取登录用户所有权限Collection<? extends GrantedAuthority> getAuthorities();// 表示获取密码String getPassword();// 表示获取用户名String getUsername();// 表示判断账户是否过期boolean isAccountNonExpired();// 表示判断账户是否被锁定boolean isAccountNonLocked();// 表示凭证{密码}是否过期boolean isCredentialsNonExpired();// 表示当前用户是否可用boolean isEnabled();}

这个类是系统默认的用户“主体”

3、UserDetailsService

在这里插入图片描述

UserDetailsService 接口实现类

当什么也没有配置的时候,账号和密码是由 Spring Security定义生成的。而在实际项目中账号和密码都是从数据库中查询出来的。所以我们要通过自定义逻辑控制认证逻辑。如果需要自定义逻辑时,只需要实现UserDetailService 接口即可。UserDetailService 接口定义如下:

package org.springframework.security.core.userdetails;/** * Core interface which loads user-specific data. * 

* It is used throughout the framework as a user DAO and is the strategy used by the * {@link org.springframework.security.authentication.dao.DaoAuthenticationProvider * DaoAuthenticationProvider}. * *

* The interface requires only one read-only method, which simplifies support for new * data-access strategies. * * @author Ben Alex * @see org.springframework.security.authentication.dao.DaoAuthenticationProvider * @see UserDetails */public interface UserDetailsService {/** * Locates the user based on the username. In the actual implementation, the search * may possibly be case sensitive, or case insensitive depending on how the * implementation instance is configured. In this case, the UserDetails * object that comes back may have a username that is of a different case than what * was actually requested.. * @param username the username identifying the user whose data is required. * @return a fully populated user record (never null) * @throws UsernameNotFoundException if the user could not be found or the user has no * GrantedAuthority */UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;}

loadUserByUsername:根据用户名定位用户。在实际实现中,搜索可能区分大小写,也可能不区分大小写,具体取决于实现实例的配置方式。在这种情况下,返回的 UserDetails 对象的用户名可能与实际请求的用户名不同
方法参数 username(表示用户名。此值是客户端表单传递过来的数据。默认情况下必须叫 username,否则无

法接收)

返回值 UserDetails

4、PasswordEncoder 密码解析器

​ SpringSecurity 要求容器中必须有PasswordEncoder实例。所以当自定义登录逻辑时要求必须给容器注入PaswordEncoder的bean对象。

4.1、接口介绍

  • encode():把参数按照特定的解析规则进行解析。
  • matches():验证从存储中获取的编码密码与编码后提交的原始密码是否匹配。如果密码匹配,则返回true;如果不匹配,则返回false。第一个参数表示需要被解析的密码。第二个参数表示存储的密码。
  • upgradeEncoding():如果解析的密码能够再次进行解析且达到更安全的结果则返回true,否则返回false。默认返回false.
    在这里插入图片描述

4.2、PaswordEncoder 实现类

在 PaswordEncoder 中内置了很多的实现类
在这里插入图片描述

4.3、BCryptPasswordEncoder

BCryptPasswordEncoder 是 Spring Security官方推荐的密码解析器,平时多使用这个解析器。

BCryptPasswordEncoder是对 berypt 强散列方法的具体实现。是基于Hash算法实现的单向加密。可以通过strength控制加密强度,默认10.

4.4、代码演示

新建测试 BCryptPasswordEncoder 用法

  1. 加密密码:

    @Testpublic void testPasswordEncoder(){    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();    String beEncodePassword = passwordEncoder.encode("WuYufan");    System.out.println("beEncodePassword = " + beEncodePassword);}

    运行结果:

    beEncodePassword = $2a$10$Nm26wey7CCxhbzuXfpgO4.UmVpJxfiekX2B2YNNfbn7hmJo3OKc4K
  2. 密码比对

    @Testpublic void testPasswordMatches(){    PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();    boolean isMatches = passwordEncoder.matches("WuYufan","$2a$10$Nm26wey7CCxhbzuXfpgO4.UmVpJxfiekX2B2YNNfbn7hmJo3OKc4K");    System.out.println("isMatches = " + isMatches);}

    运行结果:

    isMatches = true

5、设置用户名和密码

5.1、方式一:通过配置文件

在 application.yml 中增加配置

spring:  security:    user:      name: wuyufan      password: 123465

5.2、方式二:通过配置类实现

package cn.edu.hziee.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;@Configurationpublic class SpringSecurityConfig extends WebSecurityConfigurerAdapter {    @Bean    public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder();    }    @Override    protected void configure(AuthenticationManagerBuilder auth) throws Exception { String password = passwordEncoder().encode("123456"); auth.inMemoryAuthentication().withUser("wuyufan").password(password).roles("admin");    }}

5.3、方式三:自定义实现类设置(推荐)

  1. 创建配置类,设置使用哪个 UserDetailsService 实现类

    package cn.edu.hziee.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;@Configurationpublic class SpringSecurityConfig extends WebSecurityConfigurerAdapter {    @Bean    public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder();    }}
  2. 编写实现类,返回 User 对象,User 对象有用户名、密码和操作权限

    package cn.edu.hziee.service.impl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.AuthorityUtils;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.stereotype.Service;import java.util.List;@Service("userDetailsService")public class UserServiceImpl implements UserDetailsService {    @Autowired    private PasswordEncoder passwordEncoder;    @Override    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { if(!("wuyufan".equals(username))){     System.out.println("用户名不存在!");     return null; } String password = passwordEncoder.encode("123456"); List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"); return new User(username, password, authorities);    }}

上一篇:Spring Security 概述
下一篇:SpringBoot 整合 SpringSecurity——数据库实现

说说控