Spring Security 实现自定义登录和认证(1):使用自定义的用户进行认证
创始人
2024-05-29 07:04:50
0

1 SpringSecurity

1.1 导入依赖

org.springframework.bootspring-boot-starter-security

1.2 编写配置类

在spring最新版中禁用了WebSecurityConfigurerAdapter类,官方推荐采用配置类的方法进行配置。

  • 新建一个配置类,注意添加注释@EnableWebSecurity
    在这里插入图片描述

1.3 示例

  • 在类中添加一个Bean,生成过滤方法

      @Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception{http.authorizeHttpRequests((authz) -> authz.anyRequest().authenticated()).httpBasic(withDefaults());return http.build();}
    

    在这里插入图片描述

  • 忽略某个路径下的请求

      @Beanpublic WebSecurityCustomizer webSecurityCustomizer() {return (web) -> web.ignoring().requestMatchers("/level2", "/level3");}
    

    效果就是当我请求http://localhost:8080/level2的时候,就会重复跳出登录页面

1.4 自定义User实现登录

1.4.1 编写User类

在这里插入图片描述

1.4.2 定义UserRepository接口,用来实现从数据库或其它地方查询User

在这里插入图片描述

1.4.3 自定义一个类实现UserDetails接口

该类实现了UserDetails接口,这个UserDetails接口就是来查找用户名什么的。下面创建一个类,它继承了自定义的MyUser类且实现了UserDetails接口。(为什么要继承MyUser类?因为官方示例这么做的。。。)

在这里插入图片描述

package com.wjj.security.domain;import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;
import java.util.Collections;
import java.util.List;public class MyUserDetails extends MyUser implements UserDetails {//定义构造函数public MyUserDetails(MyUser myUser){super(myUser.getId(), myUser.getUsername(), myUser.getPassword());}@Overridepublic Collection getAuthorities() {return null;}@Overridepublic String getUsername() {return super.getUsername();//把这里改成父类返回的username}@Overridepublic boolean isAccountNonExpired() {return true;//改成true}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}
}

1.4.4 定义一个类实现UserDetailsService接口

这个类是用来检索用户名和密码的,该类被DaoAuthenticationProvider调用,至于DaoAuthenticationProvider是什么可以查看官方文档。

在这里插入图片描述

package com.wjj.security.service;import com.wjj.security.domain.MyUser;
import com.wjj.security.domain.UserRepository;
import jakarta.annotation.Resource;
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;@Service
public class CustomUserDetailService implements UserDetailsService {//注入编写的UserRepository@Resourceprivate UserRepository userRepository;//根据username查询user@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {MyUser user = userRepository.findUserByUsername(username);if(user == null){throw  new UsernameNotFoundException(username + " Not found");}//要返回一个UserDetails//这个东西就是前面实现的那个类//用来验证该user是否有效return new MyUserDetails(user);}
}

可以看到本节的功能就是根据username寻找User,然后返回一个UserDetails。我甚至可以在上面的函数中直接从数据库或内存中查询User,而这行代码的功能正是如此:

在这里插入图片描述



1.4.5 实现UserRepository接口进行查找用户

在前面的代码中,loadUserByUsername 中的这行代码还没有实现其中的查询逻辑,接下来进行实现。

在这里插入图片描述
编写一个类实现findUserByUsername接口

在这里插入图片描述

在数据库进行User的查找就可以在这一步中实现了

package com.wjj.security.domain;import java.util.Map;public class MyUserRepository implements UserRepository{private Map usernameToUser;public MyUserRepository(Map usernameToUser){this.usernameToUser = usernameToUser;}@Overridepublic MyUser findUserByUsername(String username) {return usernameToUser.get(username);}
}

然后将这个MyUser变成Spring的一个Resource,因为我们前面在CustomUserDetailService中引用UserRepository时用到了@Resource注释:

在这里插入图片描述

1.4.6 创建内存用户

在Application中new一个MyUserRepository实例,作为一个内存中存在的用户,并把它交给Spring托管:

package com.wjj.security;import com.wjj.security.domain.MyUser;
import com.wjj.security.domain.MyUserRepository;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;import java.util.HashMap;
import java.util.Map;@SpringBootApplication
public class SecurityApplication {public static void main(String[] args) {SpringApplication.run(SecurityApplication.class, args);}@BeanMyUserRepository myUserRepository(){MyUser user = new MyUser(1L, "username", "{bcrypt}$2a$10$h/AJueu7Xt9yh3qYuAXtk.WZJ544Uc2kdOKlHu2qQzCh/A3rq46qm");Map myUserMap = new HashMap<>();myUserMap.put("username", user);return new MyUserRepository(myUserMap);}}

代码中的那堆字母时经过加密的密码,在前端用户输入密码之后传到后端时进行了加密。


1.4.7 启动项目进行登录


在这里插入图片描述
登陆成功:

在这里插入图片描述

相关内容

热门资讯

【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
【前端】‘??‘与‘||‘有什... 0 问题 经常写const data = res.data.a ?? ''或者const d...
ChatGPT 怎么用最新详细... ChatGPT 以其强大的信息整合和对话能力惊艳了全球,在自然语言处理上面表现出了惊人...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...