首页 > 其他分享 >SpringSecurity简单自定义配置

SpringSecurity简单自定义配置

时间:2024-07-07 20:31:13浏览次数:14  
标签:自定义 配置 用户 SpringSecurity user new 认证 public

初学者对于学习SpringSecurity相关的一些简单自定义配置总结。由于自身能力并不能和大佬相比较,以下的一些内容有误或有可改进地方,希望指出,我抱有一颗谦虚好学的心保持热情,并感谢指正。

实现案例:

1.基于内存的用户认证

2.基于数据库的用户认证

3.添加用户(数据库)

4.自定义密码加密

5.自定义登录界面

文章目录

一、SpringSecurity的一些简单自定义配置?

二、环境搭建&相关依赖(无指定版本对应SpringBootVersion)

三、基于内存的用户认证

基于内存的用户认证执行流程

创建基础的Controller

静态资源index.html(基于thymeleaf编写)

SecurityConfiguration配置类 指定username和password

测试 浏览器输入http://localhost:8080跳转到login界面

四、基于数据库的用户认证

基于数据库的用户认证流程

如下图项目结构

​编辑

创建DBUserDetailsManager 模仿InMemoryUserDetailsManager 进行编写

测试

五、添加用户(数据库)

添加userController

实现saveUserDetails方法 不能单纯的使用mybatis-plus的save方法

重写DbuserDetailsManager中的createUser方法

测试 由于security默认防止csrf攻击,所以需要关闭csrf攻击进行测试

补充:使用apifox进行端口测试 由于用户认证问题会造成401状态码,可以先浏览器登录用户认证 然后F12复制登录信息中的cookie值 放入到测试用例中即可完成测试

​编辑

六、自定义密码加密

七、自定义登录界面

指定Controller

Controller指定跳转到此自定义登录界面

SecurityFilterChain中指定跳转的页面 注意login对应的是html文件名

总结


一、环境搭建&相关依赖(无指定版本对应SpringBootVersion)

1.SpringBoot 3.3.1

2.spring-boot-starter-security

3.spring-boot-starter-thymeleaf

4.thymeleaf-extras-springsecurity6

5.spring-boot-starter-web

6.lombok

7.spring-boot-starter-test

8.spring-security-test

9.mysql-connector-java(8.0.30 根据自己)

10.mybatis-plus-boot-starter 3.5.5

11.mybatis-spring 3.0.3

12.maven -3.9.8

二、基于内存的用户认证

基于内存的用户认证执行流程

程序启动时:

  1. 创建InMemoryUserDetailsManager对象
  2. 创建 User对象,封装用户名密码
  3. 使用InMemoryUserDetailsManager将User存入内存

校验用户时:

  1. SpringSecurity自动使用InMemoryUserDetailsManager的loadUserByUsername 方法从内存中 获取

User对象

  1. 在UsernamePasswordAuthenticationFilter 过滤器中的atemptAuthentication方法中将用户输入的用

户名密码和从内存中获取到的用户信息进行比较,进行用户认证

创建基础的Controller

@Controller
public class    IndexController {
    @GetMapping("/")
    public String index(){
        return "index";
    }
}

静态资源index.html(基于thymeleaf编写)

<html xml:th="https://www.thymeleaf.org">
<head>
    <title>
        Hello Spring Security
    </title>
</head>
<body>
 <h1>Hello Security</h1>
    <a th:href="@{/logout}">Log Out 1 </a>
    <a href="/logout">Log Out 2</a>
</body>
</html>

SecurityConfiguration配置类 指定username和password

@Configuration //配置类
@EnableWebSecurity  //开启springSecurity的自定义配置
public class WebSecurityConfig {
    @Bean
    public UserDetailsService userDetailsService() {
        //创建一个基于内存的用户管理器
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
        //创建UserDetails对象,用于管理用户名,用户密码,用户角色,用户权限等内容
        inMemoryUserDetailsManager.createUser(User.withDefaultPasswordEncoder().username("user").password("123").roles("User").build());
        return inMemoryUserDetailsManager;
    }
}

测试 浏览器输入http://localhost:8080跳转到login界面

三、基于数据库的用户认证

环境搭建比较麻烦,自己在数据库中创建一个user表都可以实现案例。建议使用mybatis-x插件快速生成案例环境。

基于数据库的用户认证流程

程序启动时:

  1. 创建DBUserDetailsManager对象,实现接囗UserDetailsManager, UserDetailsPasswordService

校验用户时:

  1. SpringSecurity自动使用DBUserDetailsManager的loaduserByUsername 方法从数据库中 获取User对象
  2. 在UsernamePasswordAuthenricationFilter 过滤器中的attemptAuthentication方法中将用户输入的用户名密码和从内存中获取到的用户信息进行比较,进行用户认证

如下图项目结构

创建DBUserDetailsManager 模仿InMemoryUserDetailsManager 进行编写

@Component
@SuppressWarnings({"all"})
public class DBUserDetailsManager implements UserDetailsManager, UserDetailsPasswordService {
    @Resource
    private userMapper userMapper;
    
    @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;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Collection<? extends GrantedAuthority> collection=new ArrayList<>();
        //根据用户输入在数据库中查询对应的用户
        QueryWrapper<user> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.ge("username", username);
        user user = userMapper.selectOne(userQueryWrapper);
        if(user==null){
            throw new UsernameNotFoundException(username);
        }else return new User(
                user.getUsername(),
                user.getPassword(), 
                user.getEnabled(), 
                true, //用户账户是否过期
                true,//用户凭证是否过期
                true,//用户是否未被锁定
                collection); //权限列表
    }
}

测试

四、添加用户(数据库)

添加userController

@RestController
@RequestMapping("/user")
@Slf4j
public class userController {

    @Autowired
    private userService userService;

    @PostMapping("add")
    public String saveUser(@RequestBody user user){
        log.info(user.toString());//接受到的user对象实例
        userService.saveUserDetails(user);
        return "添加成功";
    }
}

实现saveUserDetails方法 不能单纯的使用mybatis-plus的save方法

@Service
public class userServiceImpl extends ServiceImpl<userMapper, user>
    implements userService{

    @Autowired
    private DBUserDetailsManager dbUserDetailsManager;

    @Override
    public void saveUserDetails(user user) {
        UserDetails userDetails = User.withDefaultPasswordEncoder().username(user.getUsername()).password(user.getPassword()).build();
        dbUserDetailsManager.createUser(userDetails);
    }
}

重写DbuserDetailsManager中的createUser方法

    @Override
    public void createUser(UserDetails user) {
        user user1 = new user();
        user1.setUsername(user.getUsername());
        user1.setPassword(user.getPassword());
        user1.setEnabled(true);
        userMapper.insert(user1);
        log.info("添加成功");
    }

测试 由于security默认防止csrf攻击,所以需要关闭csrf攻击进行测试

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        //用于开启授权保护
        http.authorizeRequests(
                        authorize->
                                authorize.anyRequest().//开启所有用户的授权保护
                                        authenticated()) //已认证的请求会被自动授权
                .formLogin(Customizer.withDefaults())//自动生成默认的登录页和登出页 使用表单授权方式
                .httpBasic(Customizer.withDefaults());//基本授权方式
        http.csrf(csrf-> csrf.disable()); //关闭csrf保护策略
        return http.build();
    }

补充:使用apifox进行端口测试 由于用户认证问题会造成401状态码,可以先浏览器登录用户认证 然后F12复制登录信息中的cookie值 放入到测试用例中即可完成测试

五、自定义密码加密

如果没有指定密码加密算法 默认执行的是BCrypt算法 下图指定使用SHA-1加密。

工厂的静态构造方法把常用的几种密码方案都注入到了缓存Map中,默认注入的 encodingId 对应的是 BCryptPasswordEncoder加密方案,这样系统就可以达到在新存储密码可以使用 BCryptPasswordEncoder 加密方案进行加密,但是对于数据库里面以前用其他方式加密的密码也支持比对。我们可以复写该方法,然后修改这个“encodingId”的值,就可以在几种加密算法中进行切换了。

@SpringBootTest
class SecurityDemoApplicationTests {

    public static PasswordEncoder createDelegatingPasswordEncoder() {
        String encodingId = "bcrypt";
        Map<String, PasswordEncoder> encoders = new HashMap<>();
        encoders.put(encodingId, new BCryptPasswordEncoder());
        encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());
        encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());
        encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
        encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
        encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));
        encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
        encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
        return new DelegatingPasswordEncoder("SHA-1", encoders);
    }

    @Test
    public void test1(){
        PasswordEncoder encoder = SecurityDemoApplicationTests.createDelegatingPasswordEncoder();
        String result = encoder.encode("zhanghaijie");//即使明文密码相同但是生成的密文也会不同
        System.out.println("result = " + result);
    }

}

六、自定义登录界面

指定Controller

@Controller
public class loginController {

    @GetMapping("/login")
    public String login() {
        return "login"; //跳转访问下方的静态资源
    }
}

Controller指定跳转到此自定义登录界面

<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
    <title>登录</title>
</head>
<body>
<h1>登录</h1>
<div th:if="${param.error}">
    错误的用户名和密码.</div>

<!--method必须为"post"-->
<!--th:action="@{/login}" ,
使用动态参数,表单中会自动生成_csrf隐藏字段,用于防止csrf攻击
login: 和登录页面保持一致即可,SpringSecurity自动进行登录认证-->
<form th:action="@{/login}" method="post">
    <div>
        <!--name必须为"username"-->
        <input type="text" name="username" placeholder="用户名"/>
    </div>
    <div>
        <!--name必须为"password"-->
        <input type="password" name="password" placeholder="密码"/>
    </div>
    <input type="submit" value="登录" />
</form>
</body>
</html>

SecurityFilterChain中指定跳转的页面 注意login对应的是html文件名

/**
 * 此类是Security默认存在的Bean类
 */
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    //用于开启授权保护
    http.authorizeRequests(
        authorize->
        authorize.anyRequest().//开启所有用户的授权保护
        authenticated()) //已认证的请求会被自动授权
    .formLogin(form->{
        form.loginPage("/login").permitAll(); //无需授权即可访问当前页面
    }) //自定义登录界面
    .httpBasic(Customizer.withDefaults());//基本授权方式

    http.csrf(csrf-> csrf.disable()); //关闭csrf保护策略
    return http.build();
}

标签:自定义,配置,用户,SpringSecurity,user,new,认证,public
From: https://blog.csdn.net/2301_76288478/article/details/140250222

相关文章

  • MyBatis中二级缓存的配置与实现原理
    大家好,我是王有志,一个分享硬核Java技术的金融摸鱼侠,欢迎大家加入Java人自己的交流群“共同富裕的 Java 人”。上一篇文章《MyBatis中一级缓存的配置与实现原理》中,我们已经掌握了MyBatis一级缓存的配置(虽然根本不需要做什么配置)与原理,那么今天我们就来学习MyBat......
  • RedHat7.4—配置与管理iptables防火墙
    假如某公司需要Internet接入.采用iptables作为NAT服务器接入网络,为确保安全需要配置防火墙功能,要求内部仅能够访问Web、DNS及Mail三台服务器;1、内网通过防火墙访问外网1.1、配置主机网络内部Web服务器通过端口映象方式对外提供服务。内网服务器地址网卡1IP设为192.168.100.1......
  • 配置与管理squid代理服务器
    应用背景如下图所示,公司用squid作代理服务器,代理服务器内网IP地址为192.168.200.1,外网IP为192.168.200.3公司内网所用IP地址段为192.168.200.0/24,并且想用8080作为代理端口。1:配置非透明代理1.1、配置主机网络准备三台Linux主机,第一台为外网主机名为www,网卡(Vmnet1)IP为218.2......
  • RedHat7.4—配置常规网络
    配置主机名把主机名修改为hyborn方法一、使用nmtui修改主机名需要管理员权限运行su-root输入root密码后进入管理员模式运行nmtui通过上下左右选择菜单栏回车选择,进入设置系统名即可设置确定后退出      运行hostnamectlstatus命令查看主机名,查看到的主机名,即......
  • RedHat7.4—配置远程管理Linux服务器
    公司的Linux服务器需24小时不间断工作,维护工程师希望通过设置能远程管理和维护服务器。要求通过SSH及VNC远程管理,实现如下配置需求:可以通过SSH服务访问远程主机,可以使用证书登录远程主机,不需要输入远程主机的用户名和密码可以使用VNC服务访问远程主机,使用图形界面访问,桌面端口......
  • 在Linux中,内核调优配置文件名字有哪些?举例几个内核需要优化的参数配置?
    在Linux中,内核调优涉及到对系统内核的各种参数进行优化,以适应不同的工作负载和场景。这些参数主要存储在两个地方:一个是运行时动态可调的/proc/sys目录下的文件,另一个是持久化的配置文件/etc/sysctl.conf。1.内核调优配置文件/etc/sysctl.conf:这是最常用的内核参数配置文件,用......
  • srpingboot 自定义 start
    自动配置工程绑定配置文件,上逼格的start都支持自定义配置,我们也装像点~~@ConfigurationProperties("cyrus.hello")publicclassCyrusHelloProperties{//绑定配置文件cyrus.hello.username属性privateStringusername;publicStringgetUsernam......
  • Spring 配置文件加密
    前文在某些场景下,使用Spring作为开发组件时,不可避免地需要使用到配置文件,然而,对于配置文件中的某些敏感数据(如密码等信息字段),如果使用明文的方式,则可能在一定程度上导致信息泄露。为此,需要一种有效的方式来对这些字段进行加密处理,当前主流的一种加密方式就是Jasypt基本使用......
  • spring-14-Spring 提供集合的配置元素
    <list>类型用于注入一列值,允许有相同的值。   对于Spring框架来说,<list>类型是一种用于注入一列值的配置元素。它允许您在Spring应用程序上下文中创建一个列表,并将它注入到一个bean的属性中。这个列表可以包含任意数量的对象,并允许出现相同的值。下面是一个完整的示例......
  • open-iad的环境配置
        建议自己阅读README文件。        1.使用的是python3.10版本。condacreate--nameopen-iadpython=3.10    2.安装CUDA和pytorch-gpu版本    2.1安装CUDA     2.1.1先查看一下自己的所需CUDA版本(在NVIDIA控制面板中系统......