SpringSecurity源码分析以及如何解决前后端分离出现的跨域问题

解决Security前后端分离出现的跨域问题

一. Security源码分析

首先在看源码之前我们先来看这张图 , 这张图展示了Security执行的全部流程

在这里插入图片描述

从上图可知Security执行的入口是UsernamePasswordAuthenticationFilter这个抽象类 , 那我们就先从该类进行分析

1. UsernamePasswordAuthenticationFilter

在这里插入图片描述

进入源码我们可以看到该类继承了一个叫做AbstractAuthenticationProcessingFilter的类 , 而相同的是二者的类名都包含Filter , 说明二者的顶级接口都包含Filter , 而Filter中包含一个非常重要的方法doFilter , 但是作为抽象重写该方法不是必须的 , 现在我们就从继承的层级关系寻找哪个类重写了该方法

AbstractAuthenticationProcessingFilter

在这里插入图片描述

该类继承了一个GenericFilterBean抽象类 , 我们继续往上找

GenericFilterBean

在这里插入图片描述

在这里我们终于找到了Filter接口 , 那么谁重写了doFilter呢? ( 这里的是否被重写需要从上层一层一层往下找 )

在这里插入图片描述

点开结构我们发现这里并没有发现doFilter , 那么就看它的下一级嘛 , 也就是AbstractAuthenticationProcessingFilter

AbstractAuthenticationProcessingFilter

在这里插入图片描述

在这里我们也是找到了doFilter方法 , 观察其源码该方法调用了一个叫做attemptAuthentication尝试认证的方法

在这里插入图片描述

而该方法是一个抽象方法 , 必然会被子类重写 , 那么绕来绕去又要回到一开始的UsernamePasswordAuthenticationFilter

2. attemptAuthentication

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {if (this.postOnly && !request.getMethod().equals("POST")) {throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());} else {String username = this.obtainUsername(request);username = username != null ? username : "";username = username.trim();String password = this.obtainPassword(request);password = password != null ? password : "";UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);this.setDetails(request, authRequest);return this.getAuthenticationManager().authenticate(authRequest);}
}

如下所示 , 前端传输的账号与密码是通过obtainUsername这个方法进行获取的 , 那么继续来看该方法做了什么在这里插入图片描述

    @Nullableprotected String obtainUsername(HttpServletRequest request) {return request.getParameter(this.usernameParameter);}
private String usernameParameter = "username";private String passwordParameter = "password";

看完下面的代码是不是很明确了 , 账号密码是通过request.getParameter获取的而该方法 , 而该方法是获取表单数据的 , 在前后端分离的架构中拥有跨域问题 , 所以传统的Security架构无法解决这些问题 , 就需要我们自己来实现

二. 如何重写attemptAuthentication方法 , 实现数据传输

重写attemptAuthentication我们只需要继承AbstractAuthenticationProcessingFilter类并参照UsernamePasswordAuthenticationFilter原有的方法进行重新, 进行适当的修改即可

package com.itheima.security.filter;import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;/*** @program: security_demo* @description:* @author: jixu* @create: 2024-10-18 01:40**/public class MyUserNamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {protected MyUserNamePasswordAuthenticationFilter(String defaultFilterProcessesUrl) {super(defaultFilterProcessesUrl);}public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";@Overridepublic Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {if (!httpServletRequest.getMethod().equals("POST")) {throw new AuthenticationServiceException("Authentication method not supported: " + httpServletRequest.getMethod());} else {// 在这里就是出现问题的地方只需要重新修改获取账号密码的方式就行了// 这里由于我使用的是Json格式的数据进行传参 , 所以只需要获取数据, 反序列化即可ServletInputStream inputStream = httpServletRequest.getInputStream();HashMap<String,String> info = new ObjectMapper().readValue(inputStream, HashMap.class);String username = info.get(SPRING_SECURITY_FORM_USERNAME_KEY);username = username != null ? username : "";username = username.trim();String password = info.get(SPRING_SECURITY_FORM_PASSWORD_KEY);password = password != null ? password : "";UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);//this.setDetails(httpServletRequest, authRequest);return this.getAuthenticationManager().authenticate(authRequest);}}/**** @param request* @param response* @param chain* @param authResult: 用户认证信息* @throws IOException* @throws ServletException*/@Overrideprotected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {User principal = (User) authResult.getPrincipal();String username = principal.getUsername();Collection<GrantedAuthority> authorities = principal.getAuthorities();response.setContentType(MediaType.APPLICATION_JSON_VALUE);HashMap<String, String> info = new HashMap<>();info.put("code","1");info.put("msg","响应成功");// 将数据Map数据序列化成Json数据并发送response.getWriter().write(new ObjectMapper().writeValueAsString(info));}@Overrideprotected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {super.unsuccessfulAuthentication(request, response, failed);}
}

在这里我们已经将自定义的配置信息完善了 , 那么接下来再来想一个问题 , 该配置信息如何被Security识别并使用?

在Security中先来的过滤器会覆盖后来的 , 也就是当识别到一个过滤器被使用了 , 那么它后面与之相同的过滤器就会失效

所以只需要提前声明我们自定义的过滤器就行了

package com.itheima.security.config;import com.itheima.security.filter.MyUserNamePasswordAuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;/*** @program: security_demo* @description:* @author: jixu* @create: 2024-10-17 21:01**/@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}/*** 定义用户认证和授权的信息* @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin().and().logout().permitAll().and().csrf().disable().authorizeRequests();http.addFilterBefore(myUserNamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);}@Beanpublic MyUserNamePasswordAuthenticationFilter myUserNamePasswordAuthenticationFilter() throws Exception {// 构造认证过滤器对象 , 传入默认登录路径MyUserNamePasswordAuthenticationFilter myUserNamePasswordAuthenticationFilter = new MyUserNamePasswordAuthenticationFilter("/mylogin");// 认证该过滤器BeanmyUserNamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());return myUserNamePasswordAuthenticationFilter;}
}

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

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

相关文章

多ip访问网站

多ip访问网站 安装nginx [rootlocalhost ~]# dnf install nginx -y关闭防火墙&#xff0c;sulinux [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0添加多IP&#xff08;这里使用图形化模式&#xff09; [rootlocalhost ~]# nmtui [rootloca…

VSCode创建插件HelloWorld找不到指令解决办法

按照网上的教程执行yo code并且生成成功 但是F5打开调试新窗口后&#xff0c;ctrl shift P&#xff0c;输入helloworld并没有指令提示 原因&#xff1a;当前电脑安装的VSCode版本过低&#xff0c;不支持当前插件的使用&#xff08;因为自动生成的插件总是默认使用最新版VSC…

EESE 2024国际学术会议二轮征稿启动,优质稿件持续收录中

第三届环境工程与与可持续能源国际会议&#xff08;EESE 2024&#xff09;将于2024年12月在长沙召开&#xff0c;邀请多位顶尖学者分享研究成果。会议聚焦环境工程与可持续能源&#xff0c;涵盖多个领域&#xff0c;旨在搭建交流平台&#xff0c;促进产学研合作。投稿、参会形式…

Java项目-基于springboot框架的智慧外卖系统项目实战(附源码+文档)

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

springboot+uinapp基于Android的固定资产借用管理平台

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图论文效果图 前言 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 项目介绍 固定资产借用管理平台设计的目的是为用户提供使用申请、故障报修、设备归还、意见反馈等管理方…

Python+Flask接口判断身份证省份、生日、性别、有效性验证+docker部署+Nginx代理运行

这里写目录标题 一、接口样式二、部署流程2.1 镜像打包2.1.1 准备工作2.1.2 build打包2.1.3 dokcer部署运行2.1.4 Nginx代理 三、代码及文件3.1 index.py3.2 areaCodes.json3.3 Dockerfile 一、接口样式 https://blog.henryplus.cn/idcardApi/idCard/query?idcard{idcard} 如果…

【MySQL】内外连接

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;了解MySQL的内外连接。 > 毒鸡汤&#xff1a;有些事情&#xff0c;总是不明白&#xff0c;所以我不会坚持。早安! > 专栏选自&#xff1a;带你玩…

真别跟风,CISP认证只对这些人有用

CISP认证&#xff0c;作为信息安全领域的重要专业资格认证&#xff0c;受到了业界的广泛认可。 它不仅证明了持证者在信息安全方面的专业能力&#xff0c;也是许多企业和组织在招聘信息安全岗位时的重要参考标准。然而&#xff0c;CISP认证并非适合所有人。 虽然安全方向热度很…

ArkUI自定义Scroll滑动 指示器

最近项目中有个需求&#xff0c;关于滑动组件 Scroll 底部指示器跟随手势滑动等比例展示的效果&#xff0c;下图展示了要实现的效果。 自定义指示器组件 这里其实不是一个进度条&#xff0c;所以需要我们需要自定义绘制该组件&#xff0c;在鸿蒙中绘制组件单独使用&#xff0c…

九盾叉车高位显示器:重塑叉车视界,引领高位精准

在繁忙的物流与仓储中&#xff0c;叉车不仅是力量与效率的化身&#xff0c;更是精准与安全的守护者。九盾安防&#xff0c;以科技之名&#xff0c;打造叉车高位显示器&#xff0c;彻底革新了货叉升降的盲区挑战&#xff0c;为物流、仓储及码头等领域带来了前所未有的作业体验。…

arm架构ceph pacific部署

背景 合作伙伴实验室的华为私有云原来使用单点的nfs做为存储设备&#xff0c;现有两方面考量&#xff0c;业务需要使用oss了&#xff0c;k8s集群及其他机器也需要一套可扩展的分布式文件系统 部署ceph 初始机器配置规划 IP配置主机名Role10.17.3.144c8g1T数据盘ceph-node01…

2024java高频面试之JVM

说说 JVM 内存区域 程序计数器 是「程序控制流的指示器&#xff0c;循环&#xff0c;跳转&#xff0c;异常处理&#xff0c;线程的恢复等工作都需要依赖程序计数器去完成」。程序计数器是「线程私有」的&#xff0c;它的「生命周期是和线程保持一致」的&#xff0c;我们知道&a…

大模型落地实践:同花顺大模型技术应用及优化

这份完整版的大模型 LLM 学习资料已经上传CSDN&#xff0c;朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】 众所周知&#xff0c;大模型参数量大&#xff0c;通用能力强&#xff0c;综合性能好。但在同花顺业务场景中最初使用大模型的时候&#xf…

2024年制冷与空调设备安装修理证模拟考试题库及制冷与空调设备安装修理理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年制冷与空调设备安装修理证模拟考试题库及制冷与空调设备安装修理理论考试试题是由安全生产模拟考试一点通提供&#xff0c;制冷与空调设备安装修理证模拟考试题库是根据制冷与空调设备安装修理最新版教材&#…

2024年最新苹果iOS证书申请创建App详细图文流程

iOS 证书设置指南&#xff1a; 对于开发者来说&#xff0c;在没有Mac电脑或对Xcode等开发工具不熟悉的情况下&#xff0c;如何快速完成IOS证书制作和IPA文件提交至开发者中心一直是一个难题。但是现在&#xff0c;有了初雪云提供的极简工具&#xff0c;您可以轻松实现这两个任…

分布式数据库环境(HBase分布式数据库)的搭建与配置

分布式数据库环境&#xff08;HBase分布式数据库&#xff09;的搭建与配置 1. VMWare安装CentOS7.9.20091.1 下载 CentOS7.9.2009 映像文件1.2启动 VMware WorkstationPro&#xff0c;点击“创建新的虚拟机”1.3在新建虚拟机向导界面选择“典型&#xff08;推荐&#xff09;”1…

springBoot集成nacos注册中心以及配置中心

一、安装启动nacos 访问&#xff1a;http://127.0.0.1:8848/nacos/index.html#/login 二、工程集成nacos 1、引入依赖 我这里搭建的父子工程哈&#xff0c;在子工程引入 <dependencies><!-- SpringBoot Web --><dependency><groupId>org.sp…

【Golang】关于Gin框架请求参数的获取

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

基于springboot的网上服装购物商城系统

基于springboot的网上服装购物商城系统 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;idea 源码获取&#xff1a; &#x…

【conda环境打包】ubuntu的conda环境打包导出方法 conda-pack

【conda环境打包】ubuntu的conda环境打包导出方法 conda-pack 1.准备工作2.解压3.后续处理参考文献 1.准备工作 安装conda-pack pip install conda-pack激活要被打包的环境&#xff0c;打包环境之前 先激活要打包的环境 conda activate 被打包的环境打包命令 conda pack --…