spring security6.0版本入门解析

这篇具有很好参考价值的文章主要介绍了spring security6.0版本入门解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

spring Security6.0版本入门解析

一、身份证明(用户的密码存储认证)

1.核心接口:PasswordEncoder

public interface PasswordEncoder {
    
	String encode(CharSequence rawPassword);

	boolean matches(CharSequence rawPassword, String encodedPassword);
    
	default boolean upgradeEncoding(String encodedPassword) {
		return false;
	}

}

这个接口,当我们通过配置类@Bean注入时:

- encode:此方法中可以用于对密码进行自定义的加密
- matches:此方法对密码进行解密后比对,返回结果
- upgradeEncoding:此方法可以有多种操作方式,我本人用此方放来判断需要解密的密码长度是否达标后再进行解密,当然各位可以自己定义一些规则在其中

2.委派密码编码(DelegatingPasswordEncoder类)

加密后密码的格式:

{id}encodedPassword: id就是制定加密的方式,encodedPassword就是加密后的密码,所以整个部分有这个id(令牌)和encodedPassword(密码串文)组成

简单来说,就是当用户创建密码时,我们此时拥有一个加密的集合工厂,用户只要告诉这个工厂我们需要什么加密方式,工厂就已对应方式告诉对应的员工来进行加密,最后返还给用户的这种方式(上代码就明白了).

下面是官方给的列子↘

//用户想要的加密方式:bcrypt
String idForEncode = "bcrypt";

//encoders:可以看做是加密的集合工厂
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
encoders.put("pbkdf2@SpringSecurity_v5_8", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1());
encoders.put("scrypt@SpringSecurity_v5_8", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("argon2", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2());
encoders.put("argon2@SpringSecurity_v5_8", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8());
encoders.put("sha256", new StandardPasswordEncoder());

//此时这个工厂将这个用户需求:idForEncode拿到,去:encoders加密的集合工厂中找到,进行对应加密
PasswordEncoder passwordEncoder =new DelegatingPasswordEncoder(idForEncode, encoders);

从上面代码中可以看出,只需要建立对应加密集合库,用户输入对应的加密指定即可.那么这样做的优势如下了:

- 灵活的加密方式:不同的用户存储到数据中,有着不同的加密方式
- 提高了安全性
- 方便日后数据加密的变更迁移

DelegatingPasswordEncoder类:

  • 常用方法

    • //这是他的一个构造方法:1:传入对应的编码code(令牌) 2:编码加密的集合(如上面代码中的map)
      public DelegatingPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder) {
      		......
      	}
      
    • //这是他的另一个构造器:1:传入对应的编码code(令牌) 2:编码加密的集合(如上面代码中的map) 3:加密后令牌的前缀 4.加密后令牌的后缀
      //列出:{id}encodedPassword
      public DelegatingPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder,String idPrefix, String idSuffix){
      						......
      			}
      
    • //匹配默认的编码器
      public void setDefaultPasswordEncoderForMatches(PasswordEncoder defaultPasswordEncoderForMatches) {
      		if (defaultPasswordEncoderForMatches == null) {
      			throw new IllegalArgumentException("defaultPasswordEncoderForMatches cannot be null");
      		}
      		this.defaultPasswordEncoderForMatches = defaultPasswordEncoderForMatches;
      	}
      

      setDefaultPasswordEncoderForMatches: 我们加密后的密码是由令牌加密文的格式,就像’{id}adsdsdwwd231’这种组合方式,单么有令牌时,就不知道如何匹配密文,所以用此方法设置当没有令牌时,用那种密码编码器,所以此方法可用于数据库中老密码的迁移更新

    其他方法就是实现PasswordEncoder这个接口的方法(不在详解了)

  • 测试实例

    • @Test
          void testDelegatingPasswordEncoder() {
              //设置密码令牌idForEncode:为pbkdf2@SpringSecurity_v5_8的加密方式
              String idForEncode = "pbkdf2@SpringSecurity_v5_8";
              
              //密码编码库
              Map encoders = new HashMap<>();
              encoders.put("bcrypt", new BCryptPasswordEncoder());
              encoders.put("noop", NoOpPasswordEncoder.getInstance());
              encoders.put("pbkdf2", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_5());
              encoders.put("pbkdf2@SpringSecurity_v5_8", Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8());
              encoders.put("scrypt", SCryptPasswordEncoder.defaultsForSpringSecurity_v4_1());
              encoders.put("scrypt@SpringSecurity_v5_8", SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8());
              encoders.put("argon2", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_2());
              encoders.put("argon2@SpringSecurity_v5_8", Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8());
              encoders.put("sha256", new StandardPasswordEncoder());
              
              //创建实例将密码令牌和密码编码库放入其中
              DelegatingPasswordEncoder delegatingPasswordEncoder = new DelegatingPasswordEncoder(idForEncode, encoders);
              
              //加密KFC
              String encode = delegatingPasswordEncoder.encode("KFC");
              
              //输出encode = {pbkdf2@SpringSecurity_v5_8}8565ed891d8007100599707d04db6efe2bcb69ec802bc47a1511a50cc2976dcde227e6bcb10284cdf4ac31a3049d8cd4
              System.out.println("encode = " + encode);
      
              /**
               * 创建第二个类似实例,但是放入的令牌是test而不是pbkdf2@SpringSecurity_v5_8,
               * 然后再匹配KFC与去掉令牌的密文,
               * 因为没有令牌的密文匹配会报错如:IllegalArgumentException,
               * 所以通过setDefaultPasswordEncoderForMatches方法设置,当没有令牌时匹配规则为:
               * Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8()
               * 所以结果为:matches = true
               */
              Map encodeMap = new HashMap<>();
              encodeMap.put("test", new BCryptPasswordEncoder());
              DelegatingPasswordEncoder passwordEncoder = new DelegatingPasswordEncoder("test", encodeMap);
              passwordEncoder.setDefaultPasswordEncoderForMatches(Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8());
              String oldPassword = "8565ed891d8007100599707d04db6efe2bcb69ec802bc47a1511a50cc2976dcde227e6bcb10284cdf4ac31a3049d8cd4";
              boolean matches = passwordEncoder.matches("KFC", oldPassword);
              System.out.println("matches = " + matches);
          }
      

二、身份认证

1.页面配置拦截

​ 直接上代码,谁跟你藏着掖着!(咱就是简单举个例子)

package com.xu.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

/**
 * @author xu
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig{
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        //配置web授权访问,"/login","/register","/upLogin"这些统统无需权限
        http.authorizeHttpRequests().requestMatchers("/login","/register","/upLogin").permitAll()
                //成功的链接,也就是后续访问的链接放在这个里,我这里是成功页需要USER权限才能访问
                .requestMatchers("/success").hasRole("USER").and()
        /**
         * 自定义登陆页面是loginSelf.html页(这里看你模板引擎怎么配),表单提交的处理链接是"/upLogin"
         * 就是<form action="/upLogin"></form>这样,这个"/upLogin"不需要自己处理,就自己决定
         * usernameParameter和passwordParameter,就是表单提交所带的参数,
         * 这里我是"username"和"password";
         */
                .formLogin().loginPage("/loginSelf").loginProcessingUrl("/upLogin")
                .usernameParameter("username").passwordParameter("password");
        return http.build();
    }
}

这个是最新的6.0版本(编写日期:20230306),不再使用继承WebSecurityConfigurerAdapter来配置,而是使用SecurityFilterChain来进行注入,记得的一点就是必须加上@EnableWebSecurity这个注解,不然你小子找不到HttpSecurity!!!

  • requestMatchers():存放访问的路径
  • permitAll():全部允许访问
  • hasRole():需要权限
  • loginPage():配置登陆页面,这里写了,就把它默认自己自带的给不用
  • loginProcessingUrl():form提交到的处理链接,注释写的很清楚了
  • build();创建返回,记得返回要build哦

当然里面的方法还有很多,自己点进去看看吧,例如hasRole()还有hasAnyRole()可以传入多个参数.

注意:配置了loginPage不用loginProcessingUrl,默认的提交链接就是loginPage的参数,如果值配置loginProcessingUrl那么登陆页面就是默认滴!!!


2.用户授权

上面虽然配置了web的页面访问,那么用户登陆如何处理?怎么判断有没有权限?我又怎么给他权限,怎么存进去?

(炒直接代码)

UserServiceImpl类

package com.xu.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xu.pojo.User;
import com.xu.service.UserService;
import com.xu.mapper.UserMapper;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.ArrayList;

/**
* @author xu
* @description 针对表【user】的数据库操作Service实现
* @createDate 2023-03-02 11:30:20
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService, UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        /**
         * 从数据库查:User是我自己写的类,getOne()是mybatis_plus的中的方法
         * 就通过用户名查出一个用户
         */
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",username);
        User user = getOne(queryWrapper);
        if (user == null) {
            throw  new UsernameNotFoundException("没有这个用户啊!你小子!");
        }
        /**
         * 创建一个权限集合,随你放多少
         * 最后返回一个org.springframework.security.core.userdetails包下的User
         * 授权就给完了
         * 我这里授权的是USER;
         */
        ArrayList<SimpleGrantedAuthority> arrayList = new ArrayList<>();
        arrayList.add(new SimpleGrantedAuthority("ROLE_USER"));
        return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),arrayList);
    }
}

配置类:

package com.xu.config;

import com.xu.service.impl.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.SecurityFilterChain;

/**
 * @author xu
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig{
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        //配置web授权访问,"/login","/register","/upLogin"这些统统无需权限
        http.authorizeHttpRequests().requestMatchers("/login","/register","/upLogin").permitAll()
                //成功的链接,也就是后续访问的链接放在这个里,我这里是成功页需要USER权限才能访问
                .requestMatchers("/success").hasRole("USER").and()
        /**
         * 自定义登陆页面是loginSelf.html页(这里看你模板引擎怎么配),表单提交的处理链接是"/upLogin"
         * 就是<form action="/upLogin"></form>这样,这个"/upLogin"不需要自己处理,就自己决定
         * usernameParameter和passwordParameter,就是表单提交所带的参数,
         * 这里我是"username"和"password";
         */
                .formLogin().loginPage("/loginSelf").loginProcessingUrl("/upLogin")
                .usernameParameter("username").passwordParameter("password");
        return http.build();
    }
    
    //注入自定义授权
    @Bean
    UserDetailsService userDetailsService(){
        return new UserServiceImpl();
    }
}

看完还是懵逼,我来解释一下:

  • 首先看配置类,用户授权就是在UserDetailsService接口下,所以我们要进行配置
  • 所以呢我们就是实现了这个接口,然后在loadUserByUsername方法中定义了自己的处理逻辑,就是通过用户名从数据库中查出来,在授权进行的一个操作

​ 就是这么个理,有些人说你小子,咋不匹配密码啊?只查用户名?

这个是根据你输入的用户名去查出用户信息,然后创建了这个用户的信息和权限,数据库密码也在其中,然后你输入的密码呢,会再次与数据库的密码进行比对,这里就不用你操心了(关于比对规则看第一小节,也是配置好注入@Bean就行)。


三、总结

6.0.0的版本有很多区别,想花哨的玩还是得去看官方文档,我就大概摸了个入门,各位同志还须自己努力,当然适合不分离,若前后端分离的话,用不上,有更好的处理方式(哭死,自己的是前后端分离),实在看不懂去看源码,备注也有实列,推荐看HttpSecurity这玩意里面,还有就是你不会自定义配置,你就看他接口的实现类是怎么搞的,照猫画虎,不懂的类直接百度,或者看官方文档,直接给他拿捏文章来源地址https://www.toymoban.com/news/detail-480195.html

到了这里,关于spring security6.0版本入门解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Security6 最新版配置该怎么写,该如何实现动态权限管理

    Spring Security 在最近几个版本中配置的写法都有一些变化,很多常见的方法都废弃了,并且将在未来的 Spring Security7 中移除,因此又补充了一些新的内容,重新发一下,供各位使用 Spring Security 的小伙伴们参考。 接下来,我把从 Spring Security5.7 开始(对应 Spring Boot2.7 开始),各

    2024年02月12日
    浏览(45)
  • Spring Security入门教程,springboot整合Spring Security

    Spring Security是Spring官方推荐的认证、授权框架,功能相比Apache Shiro功能更丰富也更强大,但是使用起来更麻烦。 如果使用过Apache Shiro,学习Spring Security会比较简单一点,两种框架有很多相似的地方。 目录 一、准备工作 创建springboot项目 pom.xml application.yml 二、创建相关的类

    2024年02月05日
    浏览(49)
  • Spring Security OAuth2.0(3):Spring Security简单入门

    Spring Security 快速入门。 本章代码已分享至Gitee:https://gitee.com/lengcz/security-spring-security qquad Spring Secutiry 是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。由于它是Spring生态系统的一员,因此它伴随着整个Spring生态系统不断修正、升级,

    2024年02月13日
    浏览(48)
  • SSM项目集成Spring Security 4.X版本(使用spring-security.xml 配置文件方式)

    目录 前言 实战开发: 一、Spring Security整合到SSM项目 1. pom文件引入包 2. web.xml 配置 3. 添加 spring-security.xml 文件 二、Spring Security实战应用 1. 项目结构 2. pom文件引入 3. web.xml 配置 4. Spring 配置 applicationContext.xml 5. spring-security.xml 配置 6. springmvc.xml 配置 7. 创建实体类 8. DAO层实

    2024年01月24日
    浏览(47)
  • 权限管理详解:认证、授权及Spring Security配置解析

    深入探讨权限管理的重要性与实现方式,包括认证、授权概念,基于角色和资源的访问控制方案,以及Spring Security框架的概述和快速入门指南。

    2023年04月10日
    浏览(37)
  • Springboot 3 + Spring Security 6 + OAuth2 入门级最佳实践

    当我的项目基于 SpringBoot 3 而我想使用Spring Security,最终不幸得到WebSecurityConfigurerAdapter被废弃的消息。本文档就是在这样的情况下产生的。 应该基于: SpringBoot 3.x版本 JDK 17 在浏览器访问默认8080端口可以得到默认授权页面: 用户名为user,密码在控制台中自动生成: 写一个测

    2024年02月08日
    浏览(46)
  • Spring Security 6.x 系列【1】基础篇之概述及入门案例

    有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.0.4 本系列Spring Security 版本 6.0.2 源码地址:https://gitee.com/pearl-organization/study-spring-security-demo 本系列基于最新 Spring Boot 3.0 + Spring Security 6.0 版本,由浅入深,从实战到源码分析,详细讲解各种 Spring Security 的使用

    2024年02月06日
    浏览(57)
  • Spring Security 升级到 5.5.7、5.6.4 及以上启动报错出现版本不兼容解决思路

    1.背景 版本比对检测原理:检查当前系统中spring-security-web版本是否在漏洞版本范围内|版本比对检测结果:- spring-security-web 当前安装版本:5.2.1.RELEASE 需要升级到 5.5.7、5.6.4 及以上版本,因为pom中找不到直接引用的位置,所以加入以下依赖将spring-security-web版本强制升级到5.5.7 启

    2023年04月24日
    浏览(37)
  • Spring Security 6.x 系列【28】授权服务器篇之Spring Authorization Server 1.0 入门案例

    有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.0.4 本系列Spring Security 版本 6.0.2 本系列Spring Authorization Server 版本 1.0.2 源码地址:https://gitee.com/pearl-organization/study-spring-security-demo 在前几篇文档中,我们学习了 OAuth 2.0 协议,并使用 spring-security-oauth2-client 完成

    2024年02月12日
    浏览(39)
  • Spring Authorization Server入门 (八) Spring Boot引入Security OAuth2 Client对接认证服务

    在之前的文章中实现了一个认证服务,并且添加了一些自定义的内容,现在暂时没想到认证服务的新内容,本篇文章就先写一下客户端对接的吧,水一篇。 当用户通过客户端去访问一个受限的资源时,客户端会检测是否有登录信息,没有登录信息会重定向至认证服务器去请求

    2024年02月21日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包