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

    <!DOCTYPE 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.
 *
 * <p>
 * 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.
 * <p>
 * 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.
 * <p>
 * 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}.
 *
 * <p>
 * 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 <code>UserDetails</code>
	 * 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 <code>null</code>)
	 * @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. 加密密码:

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

    运行结果:

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

    @Test
    public 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;

@Configuration
public 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;
    
    @Configuration
    public 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——数据库实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bit-apk-code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值