Java17 --- SpringSecurity之自定义配置

news/2024/6/28 6:18:46

目录

一、基于用户的内存认证

 二、基于数据库用户认证

2.1、添加数据库 

2.2、添加相关pom依赖 

2.3、测试实现 

三、添加用户 

四、密码加密 

五、 自定义登录页


一、基于用户的内存认证

@Configuration
//@EnableWebSecurity //开启springSecurity自定义配置(springboot默认开启)
public class MySecurityConfig {
    @Bean
    public UserDetailsService userDetailsService() {
        //创建基于内存的用户信息管理器
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        //创建UserDetails对象,用于管理用户名,密码,角色,权限等
        manager.createUser(User.withDefaultPasswordEncoder().username("user").password("123456").roles("USER").build());
        return manager;
    }
}

 二、基于数据库用户认证

2.1、添加数据库 

#创建数据库
CREATE DATABASE `security-demo`;
#创建表
CREATE TABLE `user`(
  `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(50) DEFAULT NULL,
  `password` VARCHAR(400) DEFAULT NULL,
  `enabled` BOOLEAN NOT NULL
);
#添加唯一索引
CREATE UNIQUE INDEX `user_name_uindex` ON `user`(`name`);
#添加数据
INSERT INTO `user`(`name`,`password`,`enabled`) VALUES('admin','{bcrypt}$2a$10$FGfmxDS7Vr/xdE4bheKgFOPZjjxn74r7GV17qR0mkG9PZCT/MmmfO',TRUE),
('jack','{bcrypt}$2a$10$FGfmxDS7Vr/xdE4bheKgFOPZjjxn74r7GV17qR0mkG9PZCT/MmmfO',TRUE),
('tom','{bcrypt}$2a$10$FGfmxDS7Vr/xdE4bheKgFOPZjjxn74r7GV17qR0mkG9PZCT/MmmfO',TRUE);

2.2、添加相关pom依赖 

这里要将版本统一否则运行报错

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity6</artifactId>
        </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>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.4.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis-spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

springboot配置文件

#数据库
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/security-demo
spring.datasource.username=root
spring.datasource.password=123456
#sql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

2.3、测试实现 

实现步骤:

1、创建一个DBUserDetailsManagerConfig 类实现UserDetailsManager, UserDetailsPasswordService 接口

2、实现loadUserByUsername()方法

测试代码:

@Data
public class User {
    @TableId(value = "id",type = IdType.AUTO)
    private Integer id;
    private String name;
    private String password;
    private Boolean enabled;
}
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cjc.securitydemo.mapper.UserMapper">

</mapper>
public interface UserService extends IService<User> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {

}
@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService;
    @GetMapping("/getListUser")
    public List<User> getListUser(){
        return userService.list();
    }
}

方式一:使用@Component

@Component
public class DBUserDetailsManagerConfig implements UserDetailsManager, UserDetailsPasswordService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("name",username);
        User user = userMapper.selectOne(userQueryWrapper);
        if (user == null) {
            throw new UsernameNotFoundException(username);
        }else {
            Collection<GrantedAuthority> collection = Arrays.asList();
            return new org.springframework.security.core.userdetails.User(
                    user.getName(),
                    user.getPassword(),
                    user.getEnabled(),
                    true,//用户账号是否过期
                    true, //用户凭证是否过期
                    true, //用户是否被锁定
                    collection //权限列表
            );
        }
    }
    @Override
    public UserDetails updatePassword(UserDetails user, String newPassword) {
        return null;
    }

    @Override
    public void createUser(UserDetails user) {

    }

    @Override
    public void updateUser(UserDetails user) {

    }

    @Override
    public void deleteUser(String username) {

    }

    @Override
    public void changePassword(String oldPassword, String newPassword) {

    }

    @Override
    public boolean userExists(String username) {
        return false;
    }

方式二: 不使用@Component

@Bean
  public UserDetailsService dbUserDetailsManagerConfig(){
     return new DBUserDetailsManagerConfig();
  }

三、添加用户 

添加该依赖用于测试

<dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
            <version>4.1.0</version>
        </dependency>
 void saveUser(User user);
 @Autowired
    private DBUserDetailsManagerConfig dbUserDetailsManagerConfig;
    @Override
    public void saveUser(User user) {
        dbUserDetailsManagerConfig.createUser(org.springframework.security.core.userdetails.User
                .withDefaultPasswordEncoder()
                .username(user.getName())
                .password(user.getPassword())
                .build());
    }
@Component
public class DBUserDetailsManagerConfig implements UserDetailsManager, UserDetailsPasswordService {
    @Autowired
    private UserMapper userMapper;
    //添加用户信息
    @Override
    public void createUser(UserDetails user) {
        User myUser = new User();
        myUser.setName(user.getUsername());
        myUser.setPassword(user.getPassword());
        myUser.setEnabled(true);
        userMapper.insert(myUser);
    }
}
@PostMapping("/addUser")
    public void addUser(@RequestBody User user){
        userService.saveUser(user);
        System.out.println("添加一次");
    }

四、密码加密 

@Test
    void contextLoads() {
        //工作因子,默认为10,最小4,最大31,防止密码被暴力破解
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(4);
        String encode = bCryptPasswordEncoder.encode("123456");
        System.out.println(encode);
         if (bCryptPasswordEncoder.matches("123456", encode)){
             System.out.println("密码正确");
         }else {
             System.out.println("密码错误");
         }
    }

五、 自定义登录页

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests(
                authorize -> authorize
                        .anyRequest() //对所有请求开启授权保护
                        .authenticated() //已认证的请求会自动授权
               )
                .formLogin(
                        //Customizer.withDefaults()
                        form -> form.loginPage("/login")
                                .permitAll()//无需授权就能访问
                                .usernameParameter("name")
                                .passwordParameter("pass")
                );//使用表单授权方式
                //.httpBasic(Customizer.withDefaults());//使用基本授权方式
        httpSecurity.csrf(csrf -> csrf.disable());//关闭csrf功能
        return httpSecurity.build();
    }
@Controller
public class LoginController {

    @GetMapping("/login")
    public String getLogin(){
        return "login";
    }
}
<html xmlns:th="https://www.thymeleaf.org">
<head>
    <title>登录</title>
</head>
<body>
<h1>登录</h1>
<div th:if="${param.error}">
    错误的用户名或密码
</div>
<form th:action="@{/login}" method="post">
    <div>
        <input type="text" name="name" placeholder="用户名"/>
    </div>
    <div>
        <input type="password" name="pass" placeholder="密码"/>
    </div>
    <input type="submit" value="登录"/>
</form>
</body>
</html>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


http://lihuaxi.xjx100.cn/news/2215496.html

相关文章

机器学习笔记:focal loss

1 介绍 Focal Loss 是一种在类别不平衡的情况下改善模型性能的损失函数最初在 2017 年的论文《Focal Loss for Dense Object Detection》中提出这种损失函数主要用于解决在有挑战性的对象检测任务中&#xff0c;易分类的负样本占据主导地位的问题&#xff0c;从而导致模型难以…

LeetCode题练习与总结:最长连续序列--128

一、题目描述 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1&#xff1a; 输入&#xff1a;nums [100,4,200,1,3,2] 输出&…

linux下C语言如何操作文件(一)

本篇我们简单介绍一下在linux中如何使用C语言操作文件,首先我们在项目中创建file_util.c源文件和file_util.h头文件如图: 我们先编辑file_util.h文件,定义好常用的函数,源代码如下: #ifndef FILE_UTIL_INCLUDED #define FILE_UTIL_INCLUDED#include <stdbool.h> #i…

docker镜像拉取失败,K8s的calicoPod出现Init:ImagePullBackOff问题的解决

配置k8s集群出现问题 起初以为是版本问题&#xff0c;最后比对了一下发现没有问题。使用 kubectl describe calico-node-mg9xh -n kube-system命令查看发现docker pull 镜像失败&#xff0c;但是docker国内镜像源早就配置过了。 猜测Docker的缓存可能会导致拉取镜像失败。尝试…

将自己md文件发布到自己的博客园实现文件的持久化存储

上传markdown文件到博客园 目录 【0】需求原因【1】功能【2】环境【最佳实践测试】 &#xff08;1&#xff09;查看 Typora 设置&#xff08;2&#xff09;配置 pycnblog 配置文件 config.yaml&#xff08;3&#xff09;运行 pycnblog 中的文件 cnblog_markdown.cmd&#xff0…

边缘微型AI的宿主?—— RISC-V芯片

一、RISC-V技术 RISC-V&#xff08;发音为 "risk-five"&#xff09;是一种基于精简指令集计算&#xff08;RISC&#xff09;原则的开放源代码指令集架构&#xff08;ISA&#xff09;。它由加州大学伯克利分校在2010年首次发布&#xff0c;并迅速获得了全球学术界和工…

Qt状态机框架

概述 状态机框架提供了用于创建和执行状态图的类。这些概念和符号基于Harel的Statecharts:复杂系统的可视化形式(http://www.wisdom.weizmann.ac.il/~dharel/SCANNED.PAPERS/Statecharts.pdf)&#xff0c;也是UML状态图的基础。状态机执行的语义基于状态图XML (SCXML)(http://…

vue中的依赖管理

第1部分&#xff1a;引言 1.1 Vue框架简介 Vue.js是一个用于构建用户界面的渐进式框架。它从核心出发&#xff0c;易于学习和集成&#xff0c;同时提供丰富的生态系统支持&#xff0c;包括但不限于Vuex状态管理、Vue Router路由管理等。Vue的核心库只关注视图层&#xff0c;易…