springsecurity6使用

spring security 中的类 :

  • AuthenticationManager : 实现类:ProviderManager
    管理很多的 provider ,,, 经常使用的,DaoAuthenticationProvider , 这个要设置一个 UserDetailService , 查找数据库,,loadUserByUsername() 查找出数据库中的对象,,然后进行比对
spring security 中的配置

配置spring security 也就是配置 过滤器链,,spring security 他有默认的过滤器链,,,通过HttpSecurity 中的 build()方法,会返回一个默认的有拦截的过滤器链
我们一般都是在这个原本的过滤器链上面修改,,而不是重新创建自己的过滤器链,,


    /**
     * 过滤器
     *  : 配置过滤器链
     *  DispatchServlet
     *
     *  DefaultLoginPageGeneratingFilter : 默认登录页面过滤器
     *  DefaultLogoutPageGeneratingFilter : 默认注销页面过滤器
     *  BasicAuthenticationFilter : 请求头认证过滤器
     */


    /**
     * 配置过滤器链  SecurityFilterChain,,spring security 所有功能都是通过过滤器链来提供
     */
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 拦截所有,,经过某些过滤器
//        return new DefaultSecurityFilterChain(new AntPathRequestMatcher("/**"));


        // 默认的过滤器链
//        return http.build();


         http.authorizeHttpRequests(p->p.anyRequest().authenticated())
                .formLogin(f->f.usernameParameter("username")
                        .passwordParameter("password")
                        .loginProcessingUrl("/login")
                        .successHandler((req,resp,auth)->{
                            resp.setContentType("application/json;charset=utf-8");
                            Hr hr = (Hr) auth.getPrincipal();
                            hr.setPassword(null);
                            resp.getWriter().write(new ObjectMapper().writeValueAsString(RespBean.ok("登录成功",hr)));
                        })
                        .failureHandler((req,resp,e)->{
                            resp.setContentType("application/json;charset=utf-8");
                            RespBean error = RespBean.error("登录失败");

                            if (e instanceof BadCredentialsException){
                                error.setMessage("密码错误");
                            }else if (e instanceof DisabledException){
                                error.setMessage("用户被禁用");
                            }else if (e instanceof LockedException){
                                error.setMessage("账户被锁定");
                            }else if (e instanceof AccountExpiredException){
                                error.setMessage("账户过期");
                            }else if(e instanceof CredentialsExpiredException){
                                error.setMessage("密码过期");
                            }

                            resp.getWriter().write(new ObjectMapper().writeValueAsString(error));
                        }))
                .csrf(c->c.disable())
                 //异常处理
                 .exceptionHandling(e->e.authenticationEntryPoint((req,resp,ex)->{
                     resp.setContentType("application/json;charset=utf-8");
                     resp.setStatus(401);
                     RespBean error = RespBean.error("尚未登陆,请登录");
                     resp.getWriter().write(new ObjectMapper().writeValueAsString(error));
                 }));

         // 加到 UsernamePasswordAuthenticationFilter前面
         http.addFilterBefore(jsonFilter(), UsernamePasswordAuthenticationFilter.class);

         return  http.build();

        /**
         * spring security 默认key-value
         * UsernamePasswordAuthenticationFilter
         */

    }

UsernamePasswordAuthenticationFilter : 这个是拦截提交的用户名密码的拦截器,,,里面有个attemptAuthentication() 去获取前端传入的用户名密码,
在这里插入图片描述
根据request获取的参数,,,
然而,我们需要通过json传参,,就需要重写这个方法,,并将自己的过滤器加入到spring security的过滤器链中,,

/**
 * 登录传递json
 */
public class JsonFilter extends UsernamePasswordAuthenticationFilter {
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (!request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        String contentType = request.getContentType();
        if (contentType.equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE) || contentType.equalsIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE)){
            // 前端传入的是json
            try {
                // 通过io流,去解析请求体参数,,,比如:文件,json,,,   key-value也可以通过io流获取
                Hr hr = new ObjectMapper().readValue(request.getInputStream(), Hr.class);

                String username = hr.getUsername();
                String password = hr.getPassword();
                UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username,
                        password);
                // Allow subclasses to set the "details" property
                setDetails(request, authRequest);
                // 获取认证管理器去认证
                return this.getAuthenticationManager().authenticate(authRequest);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }else{
            //  key-value
            return super.attemptAuthentication(request,response);
        }




    }
}

自己新加的过滤器,需要配置自己的 AuthenticationManager , 和用户信息存放的位置:

   /**
     * AuthenticationManager :
     *      实现类:   ProviderManager
     *      管理很多 provider
     * @return
     */
    @Bean
    AuthenticationManager authenticationManager(){
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();

        daoAuthenticationProvider.setUserDetailsService(hrService);

        ProviderManager providerManager = new ProviderManager(daoAuthenticationProvider);
        return providerManager;
    }

配置了自己的 登录filter,, HttpSecurity中配置的formLogin 就失效了,,,需要自己配置loginProcessingUrl, successHandler,failureHandler等信息,,

需要配置自己的 AuthenticationManager 和表明登录信息的存放位子,,,,因为每一次都会从这个存放位置去找用户信息,,如果找到,表示已登录,如果没找到,就是没有登录

   /**
     * 配置了  JsonFilter ,,,    httpsecurity 中的 fromLogin就失效了
     * @return
     */
    JsonFilter jsonFilter(){
        JsonFilter jsonFilter = new JsonFilter();
        jsonFilter.setFilterProcessesUrl("/login");
        jsonFilter.setAuthenticationSuccessHandler((req,resp,auth)->{
            resp.setContentType("application/json;charset=utf-8");
            Hr hr = (Hr) auth.getPrincipal();
            hr.setPassword(null);
            resp.getWriter().write(new ObjectMapper().writeValueAsString(RespBean.ok("登录成功",hr)));
        });
        jsonFilter.setAuthenticationFailureHandler((req,resp,e)->{
            resp.setContentType("application/json;charset=utf-8");
            RespBean error = RespBean.error("登录失败");

            if (e instanceof BadCredentialsException){
                error.setMessage("密码错误");
            }else if (e instanceof DisabledException){
                error.setMessage("用户被禁用");
            }else if (e instanceof LockedException){
                error.setMessage("账户被锁定");
            }else if (e instanceof AccountExpiredException){
                error.setMessage("账户过期");
            }else if(e instanceof CredentialsExpiredException){
                error.setMessage("密码过期");
            }

            resp.getWriter().write(new ObjectMapper().writeValueAsString(error));
        });


        // 需要设置自己的 AuthenticationManager
        jsonFilter.setAuthenticationManager(authenticationManager());

        /**
         *  每一次都会从 httpSession中获取用户,,如果httpsession中没有用户,就会表示成没有登录,,
         *  新配置的 filter 需要告知 ,,用户信息存放在哪里,,
         */

        // 自己配置的filter 需要设置 SecurityContextHolder 存储用户的位置
        jsonFilter.setSecurityContextRepository(new HttpSessionSecurityContextRepository());

        return jsonFilter;
    }

这个用户信息可以存在HttpSessionSecurityContextRepositorysession中,,也可以重写类,存放在其他地方,比如redis

spring security 异常处理,,exceptionHandling, 中authenticationEntryPoint,处理登录失败异常
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

操作系统基础:IO管理概述【上】

🌈个人主页:godspeed_lucip 🔥 系列专栏:OS从基础到进阶 🏆🏆本文完整PDF源文件请翻阅至文章底部下载。🏆🏆 🎮1 I/O设备的基本概念与分类🔫1.1 总览&#x…

538. 把二叉搜索树转换为累加树

给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒一下,二叉搜索树满足下列约束条件&#…

屏幕字体种类介绍

[ Script and font support in Windows ] [Windows 中的脚本和字体支持] 在Windows 2000 以前,Windows 的每个主要版本都会添加对新脚本的文本显示支持。本文介绍了每个主要版本中的更改。 Since before Windows 2000, text-display support for new scr…

云原生之基石-Docker Compose

1. 前言 在上一篇文章中介绍了基本的Docker工具,我们对单个应用程序进行单机单进程部署,制作Dockerfile文件,执行docker build来生成docker镜像, 执行docker run来运行一个容器,自己指定需要的参数如-v,但是…

【教3妹学编程-算法题】输入单词需要的最少按键次数 I

3妹:2哥,新年好鸭~ 2哥 : 新年好,3妹这么早啊 3妹:是啊,新年第一天要起早,这样就可以起早一整年 2哥 :得,我还不了解你,每天晒到日上三竿 3妹:嘿嘿嘿嘿,一年是…

作业2.12

1、选择题 1.1、以下程序的输出结果是____A____。 main() { int k11,k22,k33,x15; if(!k1) x--; else if(k2) if(k3) x4; else x3; printf(“x%d\n”,x); } A x4 B x15 C x14 D x3 1.2、有以下程序,while循环执行____A____次。 int main&#x…

STM32自学☞定时器定时中断案例

timer_interrupt.c文件 /* 初始化函数编写步骤: 1.打开时钟 2.选择时基单元的时钟源(内部时钟源) 3.配置时基单元 4.NVIC配置 5.启动定时器 */ #include "stm32f10x.h" #include "stm32f10x_tim.h" #include …

【Linux】进程信号概念 | 核心转储 | 信号的产生

文章目录 一、信号入门1.1 生活中的信号1.2 进程角度的信号1.3 信号的概念1.4 信号的三种常见处理方式 二、信号的产生2.1 通过终端按键产生信号问题1:OS怎么知道键盘输入了ControlC ?问题2:按CtrlC终止进程和按Ctrl\终止进程,有什…

Visual Studio 2010+C#实现信源编码

1. 要求 本文设计了一套界面系统,该系统能够实现以下功能: 克劳夫特不等式的计算,并且能够根据计算结果给出相应的信息。可通过用户输入的初始条件然后给出哈夫曼编码以及LZ编码,结果均通过对话框来显示哈夫曼编码结果包含相应的…

算法沉淀——分治算法(leetcode真题剖析)

算法沉淀——分治算法 快排思想01.颜色分类02.排序数组03.数组中的第K个最大元素04.库存管理 III 归并思想01.排序数组02.交易逆序对的总数03.计算右侧小于当前元素的个数04.翻转对 分治算法是一种解决问题的算法范式,其核心思想是将一个大问题分解成若干个小问题&a…

代码控制邮件服务器发送电子邮件

1、引言 在用户注册的时候我们如果需要让用户接收动态验证码通常有两种方式。一种是给用户发送短信验证码,另一种是发送邮箱验证码。而发送短信验证码的话就必须购买短信流量,这无疑增加了投入的成本,那么此时我们可以使用发送邮箱验证码的形…

算法刷题:盛水最多的容器

盛水最多的容器 .习题链接题目题目解析算法原理我的答案 . 习题链接 盛水最多的容器 题目 题目解析 VH*W h为左右两边低的一边,w为左右两边之间的距离 算法原理 定义两个指针 left0,rightn-1; left从左往右对数组进行遍历,right从右往左进行遍历 遍历的过程中,每一次都需要…

微信小程序scroll-view组件[使用竖向横向滚动,flex布局,点击滚动到该元素及其滚动动画]

1、使用竖向横向滚动 scroll-y 属性:使用竖向滚动,必须给 scroll-view 一个固定高度 例如:height:60rpx; scroll-x 属性:使用横向滚动,必须加以下样式 1、给 scroll-view 加 width: 100%; white-space: n…

使用matplotlib库来绘制直方图

# coding: utf-8 from matplotlib import font_manager from matplotlib import pyplot as plt# 设置字体,这里使用微软雅黑字体 my_font font_manager.FontProperties(fnameC:\Windows\Fonts\msyh.ttc, size10)# 数据列表 a[131,98,125,131,124,139,131,117,128,1…

知识图谱 多模态学习 2024 最新综述

知识图谱遇见多模态学习:综述 论文题目:Knowledge Graphs Meet Multi-Modal Learning: A Comprehensive Survey 论文链接:http://arxiv.org/abs/2402.05391 项目地址:https://github.com/zjukg/KG-MM-Survey 备注:55…

第二篇【传奇开心果微博系列】Python微项目技术点案例示例:成语接龙游戏

传奇开心果微博系列 系列微博目录Python微项目技术点案例示例系列 微博目录一、微项目目标二、雏形示例代码三、扩展整体思路四、玩家输入示例代码五、成语判断示例代码六、回答判断示例代码七、电脑判断示例代码八、游戏结束示例代码九、界面优化示例代码十、扩展成语库示例代…

证明之圆的分割

圆的分割 “数学证明问题:圆上点连线分割区域总数的倍增推理” 既然我已经谈到了数学证明的本质,现在让我们回到本系列开始时的问题。圆上有n个点,我们用直线将这些点两两连结起来,希望能够表明这些直线所分割出的区域总数是 2 …

【程序设计竞赛】C++与Java的细节优化

必须强调下,以下的任意一种优化,都应该是在本身采用的算法没有任何问题情况下的“锦上添花”,而不是“雪中送炭”。 如果下面的说法存在误导,请专业大佬评论指正 读写优化 C读写优化——解除流绑定 在ACM里,经常出现…

【Java程序设计】【C00251】基于Springboot的医院信息管理系统(有论文)

基于Springboot的医院信息管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的医院信管系统 本系统分为管理员功能模块、系统功能模块以及医生功能模块。 系统功能模块:医院信管系统,…

Swift Combine 用 Future 来封装异步请求 从入门到精通十一

Combine 系列 Swift Combine 从入门到精通一Swift Combine 发布者订阅者操作者 从入门到精通二Swift Combine 管道 从入门到精通三Swift Combine 发布者publisher的生命周期 从入门到精通四Swift Combine 操作符operations和Subjects发布者的生命周期 从入门到精通五Swift Com…