spring boot(学习笔记第十二课)

spring boot(学习笔记第十二课)

  • Spring Security内存认证,自定义认证表单

学习内容:

  1. Spring Security内存认证
  2. 自定义认证表单

1. Spring Security内存认证

  1. 首先开始最简单的模式,内存认证。
    • 加入spring security的依赖。
      <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
      </dependency>
      
    • 加入controller进行测试。
       @GetMapping("/security_hello")@ResponseBodypublic String hello(){return "hello,security";}
      
    • 启动应用程序。
      默认的用户名是user,密码会在log中出现。
      Using generated security password: 9b7cd16e-af9e-4804-a6a2-9303df66ace8
      
    • 访问controller,可以看到这里在这里插入图片描述 * 输入上面的密码,进行login。
      在这里插入图片描述
  2. 接着开始在内存中定义认证的用户和密码。
    • 定义内存用户,设定安全设置@configuration
      @Configuration
      public class SecurityConfig {@BeanPasswordEncoder passwordEncoder() {return NoOpPasswordEncoder.getInstance();}@BeanUserDetailsService userDetailsService() {InMemoryUserDetailsManager users =new InMemoryUserDetailsManager();users.createUser(User.withUsername("finlay_admin").password("123456").roles("ADMIN").build());users.createUser(User.withUsername("finlay_dba").password("123456").roles("DBA").build());users.createUser(User.withUsername("finlay_super").password("123456").roles("ADMIN", "DBA").build());return users;}@BeanSecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(auth -> auth.requestMatchers("/**")//匹配所有/** url.hasRole("ADMIN")//定义/**访问所需要ADMIN的role.anyRequest()//设定任何访问都需要认证.authenticated()//设定任何访问都需要认证).csrf(csrf -> csrf.disable())//csrf跨域访问无效 Cross-Site Request Forgery.sessionManagement(session -> session.maximumSessions(1).maxSessionsPreventsLogin(true));return http.build();}
      
    • finlay_dba这个user只设定了DBArole,login是无效的
      在这里插入图片描述
    • finlay_super这个user只设定了DBArole,login是无效的
  3. 进一步 测试详细的权限设定。
    • 定义controller
       @GetMapping("/admin/hello")@ResponseBodypublic String helloAdmin() {return "hello,admin";}@GetMapping("/user/hello")@ResponseBodypublic String helloUser() {return "hello,user";}@GetMapping("/db/hello")@ResponseBodypublic String helloDB() {return "hello,DBA";}@GetMapping("/hello")@ResponseBodypublic String hello() {return "hello";}
      
    • 细化各种url的访问权限。
      @Configuration
      public class SecurityConfig {@BeanPasswordEncoder passwordEncoder() {return NoOpPasswordEncoder.getInstance();}@BeanUserDetailsService userDetailsService() {InMemoryUserDetailsManager users =new InMemoryUserDetailsManager();users.createUser(User.withUsername("finlay_user").password("123456").roles("USER").build());users.createUser(User.withUsername("finlay_admin").password("123456").roles("ADMIN").build());users.createUser(User.withUsername("finlay_dba").password("123456").roles("DBA").build());users.createUser(User.withUsername("finlay_super").password("123456").roles("ADMIN", "DBA").build());return users;}@BeanSecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {httpSecurity.authorizeHttpRequests(auth ->auth.requestMatchers("/admin/**")//匹配所有/** url.hasRole("ADMIN")//只能对于admin的role,才能访问.requestMatchers("/user/**")//匹配/user/**.hasRole("USER")//只有对于user的role,才能访问.requestMatchers("/db/**")//配置/db/**.hasRole("DBA")//只有对于dba的role,才能访问.anyRequest().authenticated()//设定任何访问都需要认证).formLogin(form -> form.loginProcessingUrl("/login")//这里对于前后端分离,提供的非页面访问url.usernameParameter("username")//页面上form的用户名.passwordParameter("password"))//页面上form的密码.csrf(csrf -> csrf.disable())//csrf跨域访问无效.sessionManagement(session -> session.maximumSessions(1).maxSessionsPreventsLogin(true));return httpSecurity.build();}
      }
      
    • 尝试访问/db/hello
      在这里插入图片描述
    • 清除chrome浏览器的session数据。
      因为没有定义logout功能,所以每次login成功之后,都不能消除login情报,这时候可以在chrome浏览器直接使用快捷键ctrl-shift-del之后进行session情报的删除。这样能够进行测试。在这里插入图片描述

2. 自定义认证表单

通常的情况是不用spring security默认提供的页面,下面进行自定义认证页面。

  1. 继续在SecurityConfigcontroller以及html中进行配置`
    • 配置自定义的认证url
       @BeanSecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {httpSecurity.authorizeHttpRequests(auth ->auth.requestMatchers("/login*").permitAll().requestMatchers("/admin/**")//匹配所有/** url.hasRole("ADMIN")//只能对于admin的role,才能访问.requestMatchers("/user/**")//匹配/user/**.hasRole("USER")//只有对于user的role,才能访问.requestMatchers("/db/**")//配置/db/**.hasRole("DBA")//只有对于dba的role,才能访问.anyRequest().authenticated()//设定任何访问都需要认证).formLogin(form -> form.loginPage("/loginPage").loginProcessingUrl("/doLogin")//这里对于前后端分离,提供的非页面访问url.usernameParameter("uname")//页面上form的用户名.passwordParameter("passwd").successHandler(new SuccessHandler())//认证成功的处理.failureHandler(new FailureHandler())//认证失败的处理.defaultSuccessUrl("/index")//默认的认证之后的页面.failureForwardUrl("/loginPasswordError"))//默认的密码失败之后的页面.exceptionHandling(exceptionHandling ->exceptionHandling.accessDeniedHandler(new CustomizeAccessDeniedHandler())).csrf(csrf -> csrf.disable())//csrf跨域访问无效.sessionManagement(session -> session.maximumSessions(1).maxSessionsPreventsLogin(true));return httpSecurity.build();}
      
      • 对于认证画面的url,进行permitAll开放,因为对于认证画面,不需要进行认证。
        auth.requestMatchers("/login*")
        .permitAll()
        
      • 定义login的认证画面url,之后会定义controllerview 注意,仅限于前后端一体程序
        .formLogin(form -> form.loginPage("/loginPage")
        
      • 定于处理认证请求的url 注意前后端一体和前后端分离程序都会使用用这个url,springboot不对这个url定义controller
         .loginProcessingUrl("/doLogin")//这里对于前后端分离,提供的非页面访问url
        
      • 对自定义页面的input进行设定,这里之后的html会使用。
        .usernameParameter("uname")//页面上form的用户名
        .passwordParameter("passwd")
        
      • 对于前后端的分离应用,直接访问doLogin,通过这里给前端返回结果对这两个类详细说明。
         .successHandler(new SuccessHandler())//认证成功的处理.failureHandler(new FailureHandler())//认证失败的处理
        
      • 如果直接访问loginPage,那么认证成功后默认的url就是这里
        注意,和successForwardUrl的区别是,successForwardUrlpost请求,这里是get请求
        .defaultSuccessUrl("/index")//默认的认证之后的页面
        
      • 配置密码失败之后的url
        .failureForwardUrl("/loginPasswordError"))//默认的密码失败之后的页面
        
      • 配置没有权限时候的错误页面的url,之后对CustomizeAccessDeniedHandler类进行说明。
        exceptionHandling(exceptionHandling ->exceptionHandling.accessDeniedHandler(new CustomizeAccessDeniedHandler()))
        
      • success handler类进行定义,主要在前后端的程序中使用。
         //success handlerprivate static class SuccessHandler implements AuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Authentication authentication) throws IOException {Object principal = authentication.getPrincipal();httpServletResponse.setContentType("application/json;charset=utf-8");PrintWriter printWriter = httpServletResponse.getWriter();httpServletResponse.setStatus(200);Map<String, Object> map = new HashMap<>();map.put("status", 200);map.put("msg", principal);ObjectMapper om = new ObjectMapper();printWriter.write(om.writeValueAsString(map));printWriter.flush();printWriter.close();}
        
      • failure handler类进行定义,主要在前后端的程序中使用。
         //failure handlerprivate static class FailureHandler implements AuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,AuthenticationException authenticationException) throws IOException {httpServletResponse.setContentType("application/json;charset=utf-8");PrintWriter printWriter = httpServletResponse.getWriter();httpServletResponse.setStatus(401);Map<String, Object> map = new HashMap<>();map.put("status", 401);if (authenticationException instanceof LockedException) {map.put("msg", "账户被锁定,登陆失败");} else if (authenticationException instanceof BadCredentialsException) {map.put("msg", "账户输入错误,登陆失败");} else {map.put("msg", "登陆失败");}ObjectMapper om = new ObjectMapper();printWriter.write(om.writeValueAsString(map));printWriter.flush();printWriter.close();}
        
      • CustomizeAccessDeniedHandler类进行定义,对没有权限等情况进行定义。比如,需要的roleADMIN,但是认证结束后的role确是DBA
        private static class CustomizeAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {response.sendRedirect("/loginNoPermissionError");}}
        
    • controller层做出一个LoginController 注意,为了定义permitAll方便,统一采用login`开头
      @Controller
      public class LoginController {@GetMapping("/loginPage")public String loginPage() {return "login";}@GetMapping("/loginNoPermissionError")public String loginNoPermission() {return "no_permission_error";}@GetMapping("/loginPasswordError")public String loginError(Model model) {model.addAttribute("message", "认证失败");return "password_error";}@PostMapping("/loginPasswordError")public String loginErrorPost(Model model) {model.addAttribute("message", "认证失败");return "password_error";}
      }
      
    • 定义view层的各个html 注意,前后端分离程序
      • login的认证画面view
        <!DOCTYPE HTML>
        <html xmlns:th="http://www.thymeleaf.org/" lang="en">
        <head><meta charset="UTF-8"><title>Spring Security 用户自定义认证画面</title>
        </head>
        <body>
        <h1>自定义用户登陆</h1>
        <form th:action="@{/doLogin}" method="post">用户名:<input type="text" name="uname"><br>密码:<input type="text" name="passwd"><br><input type="submit" value="登陆">
        </form>
        </body>
        </html>
        
      • 定义密码错误的认证错误画面view
        <!DOCTYPE HTML>
        <html xmlns:th="http://www.thymeleaf.org/" lang="en">
        <head><meta charset="UTF-8"><title>Spring Security 用户自定义-密码输入错误</title>
        </head>
        <body>
        <h1>自定义用户登陆错误-用户密码输入错误"</h1>
        </form>
        </body>
        </html>
        
      • 定义没有权限的认证错误画面view,比如需要ADMINrole,但是用户只有DBArole
        <!DOCTYPE HTML>
        <html xmlns:th="http://www.thymeleaf.org/" lang="en">
        <head><meta charset="UTF-8"><title>Spring Security 用户自定义-权限不足</title>
        </head>
        <body>
        <h1>"用户自定义画面,权限不足"</h1>
        </form>
        </body>
        </html>
        
  2. 验证结果
    • DBA用户访问http://localhost:8080/db/hello在这里插入图片描述
    • 输入错误密码
      在这里插入图片描述
    • USERrole用户登录,但是访问http://localhost:8080/db/hello,需要DBArole
      在这里插入图片描述

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

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

相关文章

JDBC的基本认识

前提 在了解和学习JDBC之前&#xff0c;大家 已经学习过 java语言 和数据库的基本知识了&#xff0c;今天这篇博客的核心&#xff0c;就是告诉大家 &#xff0c;jdbc 是连接java编译器和数据库&#xff0c;是使用java对数据库进行操作的。 正文 JDBC简介 概念 JDBC的本质 1…

【软件分享】气象绘图软件Panoply

气象是大气中的物理现象&#xff0c;气象要素则是表明大气物理状况的要素&#xff0c;主要的气象要素有降水、风、气压、湿度等。为了研究气象要素在空间上的分布和运动状况&#xff0c;我们需要对气象要素进行空间上进行可视化&#xff0c;这个时候就需要气象领域的一些的绘图…

机械设计师转大模型岗位,我是抓住风口的猪,真能起飞!

大模型&#xff08;如人工智能、机器学习和深度学习模型&#xff09;可以通过提供先进的模拟、优化和自动化工具来赋能机械设计师。这些工具可以帮助机械设计师更高效地完成设计任务&#xff0c;优化产品设计&#xff0c;并提高创新速度。以下是机械设计师如何转行大模型&#…

Monaco 多行提示的实现方式

AI 代码助手最近太火爆&#xff0c;国内有模型厂商都有代码助手&#xff0c;代码助手是个比较典型的 AI 应用&#xff0c;主要看前端&#xff0c;后端的模型都差不多&#xff0c;国内外都有专门的代码模型。现在都是集中在 VSCode 和 Idea的插件&#xff0c;本文通过 Monaco 实…

uniapp实现光标闪烁(配合自己的键盘)

前言 因为公司业务需要&#xff0c;所以我们... 演示 其实就是Chat自动打字效果 代码 键盘请看这篇文件 <template> <view class"list"><view class"title"><text>手机号码</text></view><view class"ty…

CTFShow的RE题(四)

真的是签到 给的是无后缀的 zip 文件&#xff0c;解压发现需要密码&#xff0c;也没有提示&#xff0c;猜测可能是 zip 伪加密 &#xff08;走错厂了吧&#xff09; zip是否加密 首先就是看开头的6 &#xff0c;7byte&#xff0c;和中间 01 02 后的 5 &#xff0c;6byte 成功解…

Proxifier代理的其他妙用方法(内网渗透、反溯源、小程序公众号)

目录 配置说明 1. 通过Proxifier进行内网渗透 2. 通过Proxifier将VM虚拟机代理 3. 通过Proxifier进行小程序抓包 4. 补充 文章截取处 配置说明 配置其他的之前,要新增一个代理规则,如下: 127.0.0.1; ::1 让它 Direct (直接连接,即不走任何代理)即可 说明: ::1是I…

LabVIEW透视变换

透视变换概述源程序在www.bjcyck.com下载 透视变换是一种几何变换&#xff0c;用于对图像进行扭曲&#xff0c;使其看起来从不同角度拍摄。这在计算机视觉和图像处理领域非常重要&#xff0c;例如在投影校正和图像配准中。LabVIEW提供了强大的图像处理工具&#xff0c;利用其V…

南方CASS:地理信息系统的卓越之选

引言 作为一名长期从事地理信息系统&#xff08;GIS&#xff09;工作的专业人士&#xff0c;我对各类地理信息处理软件有着深入的了解和使用经验。其中&#xff0c;南方CASS&#xff08;南方测绘计算机辅助设计系统&#xff09;无疑是我最为推崇的一款软件。它不仅功能强大&am…

无人机群辅助边缘计算系统的任务卸载和资源分配联合优化

源自&#xff1a;系统工程与电子技术 作者&#xff1a;刘世豪 黄仰超 胡航 司江勃 韩蕙竹 安琪 注&#xff1a;若出现无法显示完全的情况&#xff0c;可 V 搜索“人工智能技术与咨询”查看完整文章 摘 要 为提升无人机群辅助边缘计算系统在负载不均衡场景下的性能, 构…

maxwell启动报错:Could not find first log file name in binary log index file

出现该问题是因为&#xff1a;maxwell 读取的是 mysql 的 binlog 日志&#xff0c;而配置文件中的两个值与 binlog 的最新值没有保持一致导致 1. 切换到maxwell的库 show master status;记住图片中的 FIle 和 Position 2. 修改maxwell的配置 SELECT * from positions p ;将…

Vue3 项目中 svg 图标的封装及使用

安装 npm install vite-plugin-svg-icons -D在 vite.config.ts 中配置插件&#xff1a; import { createSvgIconsPlugin} from vite-plugin-svg-icons; import path from path;plugins: [createSvgIconsPlugin({iconDirs: [path.resolve(process.cwd(), src/assets/icons)],s…

Java并发关键字

并发关键字 关键字: synchronized详解关键字: volatile详解关键字: final详解 # Synchronized可以作用在哪里? 对象锁方法锁类锁 # Synchronized本质上是通过什么保证线程安全的? 加锁和释放锁的原理 深入JVM看字节码&#xff0c;创建如下的代码&#xff1a; public cl…

探索TXE、TC、RXNE标志位在串口通信中的轮询与中断应用

浅谈一下STM32串口中断之TXE,TC,RXNE标志位 之前做一个项目&#xff0c;用到了串口中断&#xff0c;但是对TXE、TC和RXNE标志位的作用和使用方法不是很清楚&#xff0c;导致在调试过程中遇到了一些问题。通过查阅相关资料和实际操作&#xff0c;我对这三个标志位有了更深入的了…

【机器学习】——决策树模型

&#x1f4bb;博主现有专栏&#xff1a; C51单片机&#xff08;STC89C516&#xff09;&#xff0c;c语言&#xff0c;c&#xff0c;离散数学&#xff0c;算法设计与分析&#xff0c;数据结构&#xff0c;Python&#xff0c;Java基础&#xff0c;MySQL&#xff0c;linux&#xf…

材料科学SCI期刊,IF=6+,2个月录用,审稿速度非常快

一、期刊名称 Journal of Materials Research and Technology 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;材料科学 影响因子&#xff1a;6.2 中科院分区&#xff1a;2区 三、期刊简介 《材料研究与技术杂志》为发表与材料加工、性能和性能相关的理论…

el-tree 获取当前勾选节点的选中状态以及选中值对象 触发check-change多次事件问题原因

1.需求 现在需要一个树状结构的资产树 但是现在需求是 获取当前选中的值的状态是选中还是取消选中 然后再用当前选中 or 取消选中的值 进行 选中 or 取消选中的操作 一开始使用的是 check-change 方法 接收参数如图 但是我勾选父节点 或者 子节点后 他会打印一堆数据 是因…

园区智慧能源可视化:智能监控与优化能源管理

通过图扑可视化技术&#xff0c;搭建智慧光伏园区&#xff0c;实时监控园区光伏系统的运行状态&#xff0c;分析数据并优化能源管理&#xff0c;提高发电效率和维护效率&#xff0c;助力园区实现绿色可持续发展。

Java-01-源码篇-04集合-04-Properties

目录 一&#xff0c;简介 二&#xff0c;源码讲解 2.1 Properties 继承结构 2.2 Properties 属性分析 2.3 Properties 构造器 2.4 Properties 加载配置资源文件 2.4.1 load(inputStream) 2.4.2 load(Reader) 2.4.3 load0(LineReader lr) 2.4.4 load测试 2.5 Properti…

电子产品分销商 DigiKey 在新视频系列中探索智能城市中的AI

电子产品分销商DigiKey推出了一系列新视频&#xff0c;深入探讨了AI在智能城市中的集成应用。这个名为“智能世界中的AI”的系列是其“城市数字”视频系列的第四季&#xff0c;它审视了城市环境中从基础设施到公共服务的多种AI硬件和软件的部署情况。 该系列由电子制造商莫仕&…