SpringSecurity6.x使用教程

news2025/2/24 12:37:25

SpringSecurity6.x使用

SpringSecurity版本

SpringSecurity目前支持的版本如下图所示,可以看到5.x的版本过几年就不会再维护了,6.x将成为主流。
在这里插入图片描述

入门

引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

编写测试代码

@RestController
@RequestMapping("/test")
public class TestController {


    @GetMapping("/test1")
    public String test1() {
        return "Spring Security Demo";
    }
}

启动项目后,会跳转到下图的登录页
在这里插入图片描述
用户名是user,密码则会打印在控制台,输入用户名和密码以后就可以登录了。

这个页面是在DefaultLoginPageGeneratingFilter的generateLoginPageHtml方法中生成的,而密码则是在UsernamePasswordAuthenticationFilter中生成的。

配置用户和密码

yml配置
spring:
  application:
    name: SpringSecurityDemo
  security:
    user:
      name: admin  #用户名
      password: 888888  #密码
      roles:   #用户具有的角色
        - admin

使用配置类配置

    @Bean
    public UserDetailsService userDetailsService() {
        //使用hash加密
        UserDetails user = User.withUsername("admin")
                .password("{bcrypt}admin")
                .roles("USER")
                .build();
        
        //使用bcrypt加密
        UserDetails root = User.withUsername("root").password(bCryptPasswordEncoder().encode("123456"))
                .roles("admin", "user").build();

        //密码前面需要添加{id},id加密算法的名称,不然会报错,noop是不加密
        UserDetails root1 = User.withUsername("root1").password("{noop}123456")
                .roles("admin", "user").build();

        return new InMemoryUserDetailsManager(user, root, root1);
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

常用的Handler

SpirngSecurity提供了针对各种异常处理的Handler,比如登录错误处理Handler、登录成功处理Handler等,我们只需要继承这些Handler实现自定义的逻辑即可。

登录成功登录失败

登录失败处理逻辑

@Component
public class LoginFailHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("登录失败");
        exception.printStackTrace();
    }
}

登录成功处理逻辑

@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        System.out.println("登录成功");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("登录成功");
    }
}

退出登录

成功退出登录时的处理逻辑

@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Object principal = authentication.getPrincipal();
        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write(JSON.toJSONString(principal));
        out.flush();
        out.close();
    }

}

授权失败

没有访问权限时的处理逻辑

@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        System.out.println("授权失败处理");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("没有访问权限");
        accessDeniedException.printStackTrace();

    }
}

Spring Security配置

如果想实现更多自定义的内容,则需要对SpringSecurity进行配置,比如上面自定义的登录成功Handler需要配置后才能生效。
配置主要内容如下:

  1. 登录配置:设置自定义登录页、登录接口、登录成功失败处理逻辑以及认证成功后跳转路径
  2. 授权配置:主要是设置哪些接口不需要登录认证就能访问,哪些接口需要登录认证后才能访问

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        //表单提交
        httpSecurity.formLogin(formLogin -> formLogin
                //自定义登录页地址
                .loginPage("/login.html")
                .successHandler(loginSuccessHandler)
                .failureHandler(loginFailHandler)
                //登录接口
                .loginProcessingUrl("/test/login")
                //认证成功后跳转的路径
                .defaultSuccessUrl("/index.html"));

        //授权配置
        httpSecurity.authorizeHttpRequests(authorize -> authorize
                //设置哪些路径可以直接访问,不需认证
                .requestMatchers("/login.html", "/test/login", "/swagger-ui/index.html").permitAll()
                //其他的路径都需要认证
                .anyRequest().authenticated());

        //退出登录成功处理器
        httpSecurity.logout(logout -> logout.logoutSuccessHandler(logoutSuccessHandler));

        //授权失败处理配置
        httpSecurity.exceptionHandling(exceptionHandling ->
                exceptionHandling.accessDeniedHandler(accessDeniedHandler));

        //禁用csrf
        httpSecurity.csrf(csrf -> csrf.disable());

        //设置自定义的UserDetailService,如果自定了UserDetailService,则需要设置这个
        httpSecurity.userDetailsService(userDetailsService);

        return httpSecurity.build();
    }

这个配置里需要注意的是loginProcessingUrl配置,loginProcessingUrl的作用是用来拦截前端页面对/login/doLogin这个的请求的,如果拦截到了就会走自己的请求,比如MyUserDetailService的loadUserByUsername方法。

完整代码

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<form action="/test/login" method="post">
    用户名:<input type="text" name="username"/><br/>
    密码:<input type="password" name="password"/><br/>
    <input type="submit" value="提交"/>
</form>

</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
index html
</body>
</html>

UserDetailService

@Service
public class MyUserDetailService implements UserDetailsService {



    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //根据username从数据库中获取用户信息,并封装成UserDetails对象,SpringSecurity会根据返回的UserDetails和用户输入的密码进行比对
        String user = "root1";
        String password = "root1";
        return  User.withUsername(user)
                .password(new BCryptPasswordEncoder().encode(password))
                .roles("USER")
                .build();
    }

}

Spring Secruity的配置,使用到的相关Handler在上文已经给出了

@Configuration
@EnableWebSecurity
public class SecurityConfig  {

    @Autowired
    private LoginFailHandler loginFailHandler;

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    private MyAccessDeniedHandler accessDeniedHandler;

    @Autowired
    private UserDetailsService userDetailsService;


    @Autowired
    private LogoutSuccessHandler logoutSuccessHandler;

    @Bean
    public UserDetailsService userDetailsService() {
        //使用hash加密
        UserDetails user = User.withUsername("admin")
                .password("{bcrypt}admin")
                .roles("USER")
                .build();

        //使用bcrypt加密
        UserDetails root = User.withUsername("root").password(bCryptPasswordEncoder().encode("123456"))
                .roles("admin", "user").build();

        //密码前面需要添加{id},id加密算法的名称,不然会报错,noop是不加密
        UserDetails root1 = User.withUsername("root").password("{noop}123456")
                .roles("admin", "user").build();

        return new InMemoryUserDetailsManager(user, root, root1);
    }


    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }



    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        //表单提交
        httpSecurity.formLogin(formLogin -> formLogin
                //自定义登录页地址
                .loginPage("/login.html")
                .successHandler(loginSuccessHandler)
                .failureHandler(loginFailHandler)
                //登录接口
                .loginProcessingUrl("/test/login")
                //认证成功后跳转的路径
                .defaultSuccessUrl("/index.html"));

        //授权配置
        httpSecurity.authorizeHttpRequests(authorize -> authorize
                //设置哪些路径可以直接访问,不需认证
                .requestMatchers("/login.html", "/test/login", "/swagger-ui/index.html").permitAll()
                //其他的路径都需要认证
                .anyRequest().authenticated());

        //退出登录成功处理器
        httpSecurity.logout(logout -> logout.logoutSuccessHandler(logoutSuccessHandler));

        //授权失败处理配置
        httpSecurity.exceptionHandling(exceptionHandling ->
                exceptionHandling.accessDeniedHandler(accessDeniedHandler));

        //禁用csrf
        httpSecurity.csrf(csrf -> csrf.disable());

        //设置自定义的UserDetailService,如果自定了UserDetailService,则需要设置这个
        httpSecurity.userDetailsService(userDetailsService);


        return httpSecurity.build();
    }

}

参考

  1. Spring Security官网
  2. SpringSecurity的 loginProcessingUrl为什么不能用
  3. spring security loginProcessingUrl无效问题

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1902209.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

法国工程师IMT联盟 密码学及其应用 2022年期末考试

1 密码学 1.1 问题1 对称加密&#xff08;密钥加密) 1.1.1 问题 对称密钥la cryptographie symtrique和公开密钥有哪些优缺点&#xff1f; 1.1.1.1 对称加密&#xff08;密钥加密)的优缺点 1.1.1.1.1 优点 加解密速度快encrypt and decrypt&#xff1a;对称加密算法通常基于…

智能家居安防系统教学解决方案

前言 随着科技的不断进步和智能家居概念的深入人心&#xff0c;智能家居安防系统作为智能家居领域的重要组成部分&#xff0c;其重要性日益凸显。智能家居安防系统不仅能够提供环境和人员的监测功能&#xff0c;还能够采取措施降低或避免人员伤亡及财产损失。因此&#xff0c;…

XXL-JOB中断信号感知

目录 背景 思路 实现逻辑 总结 背景 在使用xxl-job框架时&#xff0c;由于系统是由线程池去做异步逻辑&#xff0c;然后主线程等待&#xff0c;在控制台手动停止时&#xff0c;会出现异步线程不感知信号中断的场景&#xff0c;如下场景 而此时如果人工在控制台停止xxl-job执…

超越YOLO! RT-DETR 实时目标检测技术介绍

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

Thisjavabean对象数组

This 1.概念 this是一个对象this是一个构造函数 2.介绍 解决局部变量和成员变量命名冲突 this在面向对象-封装那一篇里&#xff0c;有被两个地方提及。 但我们先简单给一个例子&#xff1a; public Person(String name, String phone, String qqPassword, String bankCar…

【踩坑】修复报错Cannot find DGL libdgl_sparse_pytorch_2.2.0.so

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 错误复现 原因分析 解决方法 错误复现 import dgldataset dgl.data.CoraGraphDataset() graph dataset[0] graph.adjacency_matrix() 原因分…

Python 学习中什么是元组,如何使用元组?

什么是元组 元组&#xff08;Tuple&#xff09;是Python内置的一种数据结构&#xff0c;用于存储多个数据项。与列表类似&#xff0c;元组也可以存储不同类型的数据&#xff0c;但它们之间存在一个重要区别&#xff1a;元组是不可变的&#xff0c;也就是说&#xff0c;一旦创建…

笔记13:switch多分支选择语句

引例&#xff1a; 输入1-5中的任意一共数字&#xff0c;对应的打印字符A,B,C,D,E int num 0; printf("Input a number[1,5]:"); scanf("%d"&#xff0c;&num); if( num 1)printf("A\n"); else if(num2)printf("B\n"); else i…

文化财经macd顶底背离幅图指标公式源码

DIFF:EMA(CLOSE,12) - EMA(CLOSE,26); DEA:EMA(DIFF,9); MACD:2*(DIFF-DEA),COLORSTICK; JC:CROSS(DIFF,DEA); SC:CROSSDOWN(DIFF,DEA); N1:BARSLAST(JC)1; N2:BARSLAST(SC)1; HH:VALUEWHEN(CROSSDOWN(DIFF,DEA),HHV(H,N1));//上次MACD红柱期间合约最大值 HH2:VALUEWHE…

HTML(26)——平面转换-旋转-多重转换-缩放

旋转 属性&#xff1a;transform:rotate(旋转角度) 角度的单位是deg。 取值为正&#xff0c;顺时针旋转取值为负&#xff0c;逆时针旋转 默认情况下&#xff0c;旋转的原点是盒子中心点 改变旋转的原点可以使用属性:transform-origin:水平原点位置 垂直原点位置 取值&a…

springboot+vue原创歌曲分享平台 LW +PPT+源码+讲解

3 平台分析 3.1平台可行性分析 3.1.1经济可行性 由于本平台是作为毕业设计平台&#xff0c;且平台本身存在一些技术层面的缺陷&#xff0c;并不能直接用于商业用途&#xff0c;只想要通过该平台的开发提高自身学术水平&#xff0c;不需要特定服务器等额外花费。所有创造及工作…

[BJDCTF 2nd]简单注入

sqlsqlsqlsqlsql又来喽 过滤了单双引号&#xff0c;等于符号&#xff0c;还有select等&#xff0c;但是这里没有二次注入 。扫描发现hint.txt 看出题人的意思是&#xff0c;得到密码即可获得flag。 select * from users where username$_POST["username"] and passw…

编写优雅Python代码的20个最佳实践

想要让你的代码像艺术品一样既实用又赏心悦目吗&#xff1f;今天我们就来聊聊如何通过20个小技巧&#xff0c;让你的Python代码从平凡走向优雅&#xff0c;让同行看了都忍不住点赞&#xff01; **温馨提示&#xff1a;更多的编程资料&#xff0c;领取方式在&#xff1a; 1. 拥…

最小代价生成树实现(算法与数据结构设计)

课题内容和要求 最小代价生成树的实现&#xff0c;分别以普利姆算法和克鲁斯卡尔算法实现最小代价生成树&#xff0c;并分析两种算法的适用场合。 数据结构说明 普利姆算法实现最小代价生成树的图采用邻接表存储结构&#xff0c;还有辅助数据结构&#xff0c;数组nearest&am…

Lambda架构

1.Lambda架构对大数据处理系统的理解 Lambda架构由Storm的作者Nathan Marz提出&#xff0c;其设计目的在于提供一个能满足大数据系统关键特性的架构&#xff0c;包括高容错、低延迟、可扩展等。其整合离线计算与实时计算&#xff0c;融合不可变性、读写分离和复杂性隔离等原则&…

揭秘“消费即收益”的循环购模式 商家智慧还是消费陷阱?

大家好&#xff0c;我是你们的电商策略顾问吴军。今天&#xff0c;我将带大家深入剖析一种新兴的商业模式——循环购模式&#xff0c;它以其独特的“消费赠礼、每日返利、提现自由”特性&#xff0c;在电商界掀起了不小的波澜。那么&#xff0c;这种模式究竟有何魅力&#xff1…

ip地址突然变了一个城市怎么办

在数字化日益深入的今天&#xff0c;IP地址不仅是网络连接的标识&#xff0c;更是我们网络行为的“身份证”。然而&#xff0c;当您突然发现您的IP地址从一个城市跳转到另一个城市时&#xff0c;这可能会引发一系列的疑问和担忧。本文将带您深入了解IP地址突变的可能原因&#…

Android ViewPostImeInputStage输入事件处理

InputDispatcher向InputChannel使用socket写入输入事件&#xff0c;触发InputEventReceiver调用来接收输入事件。 ViewPostImeInputStage处理view控件的事件 frameworks/base/core/java/android/view/InputEventReceiver.java dispatchInputEvent frameworks/base/core/jav…

Shell编程类-网站检测

Shell编程类-网站检测 面试题参考答法 a(1 2 3 4) echo ${a[0]} echo ${a[*]}这里声明一个数值&#xff0c;并选择逐个调用输出还是全部输出 curl -w %{http_code} urL/IPADDR常用-w选项去判断网站的状态&#xff0c;因为不加选择访问到的网站可能出现乱码无法判断是否网站down…

Nuxt框架中内置组件详解及使用指南(一)

title: Nuxt框架中内置组件详解及使用指南&#xff08;一&#xff09; date: 2024/7/6 updated: 2024/7/6 author: cmdragon excerpt: 本文详细介绍了Nuxt框架中的两个内置组件和的使用方法与功能。确保包裹的内容仅在客户端渲染&#xff0c;适用于处理浏览器特定功能或异步…