2.SpringSecurity在mvc项目中的使用

SpringSecurity认证过程

参考

来源于黑马程序员: 手把手教你精通新版SpringSecurity

设置用户状态

用户认证业务里,我们封装User对象时,选择了三个构造参数的构造方法,其实还有另一个构造方法:

public User(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority>
authorities) {if (username != null && !"".equals(username) && password != null) {this.username = username;this.password = password;this.enabled = enabled;this.accountNonExpired = accountNonExpired;this.credentialsNonExpired = credentialsNonExpired;this.accountNonLocked = accountNonLocked;this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));} else {throw new IllegalArgumentException("Cannot pass null or empty values to constructor");}
}

可以看到,这个构造方法里多了四个布尔类型的构造参数,其实我们使用的三个构造参数的构造方法里这四个布尔 值默认都被赋值为了true,那么这四个布尔值到底是何意思呢?

  • boolean enabled 是否可用
  • boolean accountNonExpired 账户是否失效
  • boolean credentialsNonExpired 密码是否失效
  • boolean accountNonLocked 账户是否锁定

image-20200919214537040

在蘑菇博客中,就是这里进行定义的,然后在通过下面代码来进行判断该用户是否处于正常

    /*** 通过管理员Admin,生成一个SpringSecurity用户* @param admin* @return*/public static SecurityUser create(Admin admin) {boolean enabled = admin.getStatus() == EStatus.ENABLE;return new SecurityUser(admin.getUid(),admin.getUserName(),admin.getPassWord(),enabled,mapToGrantedAuthorities(admin.getRoleNames()));}

注销功能

注意:一旦开启了csrf防护功能,logout处理器便只支持POST请求方式了!修改header.jsp中注销请求:

<form action="${pageContext.request.contextPath}/logout" method="post"><security:csrfInput/><input type="submit" value="注销">
</form>

记住我功能

流程分析

还记得前面咱们分析认证流程时,提到的记住我功能吗?现在继续跟踪找到AbstractRememberMeServices对象的loginSuccess方法:

image-20200919215441535

再点进去上面if判断中的rememberMeRequested方法,还在当前类中

image-20200919215510847

image-20200919215502008

如果上面方法返回true,就表示页面勾选了记住我选项了。继续顺着调用的方法找到PersistentTokenBasedRememberMeServices的onLoginSuccess方法:

image-20200919215604473

记住我功能页面代码

注意name和value属性的值不要写错哦!

image-20200919215750642

先测试一下,认证通过后,关掉浏览器,再次打开页面,发现还要认证!为什么没有起作用呢?这是因为remember me功能使用的过滤器RememberMeAuthenticationFilter默认是不开启的!

开启remember me过滤器

<!--设置可以用spring的el表达式配置Spring Security并自动生成对应配置组件(过滤器)-->
<security:http auto-config="true" use-expressions="true"><!--省略其余配置--><!--开启remember me过滤器,设置token存储时间为60秒--><security:remember-me token-validity-seconds="60"/>
</security:http>

说明:RememberMeAuthenticationFilter中功能非常简单,会在打开浏览器时,自动判断是否认证,如果没有则 调用autoLogin进行自动认证。

remember me安全性分析

记住我功能方便是大家看得见的,但是安全性却令人担忧。因为Cookie毕竟是保存在客户端的,很容易盗取,而且 Cookie的值还与用户名、密码这些敏感数据相关,虽然加密了,但是将敏感信息存在客户端,还是不太安全。那么 这就要提醒喜欢使用此功能的,用完网站要及时手动退出登录,清空认证信息。

此外,SpringSecurity还提供了remember me的另一种相对更安全的实现机制 :在客户端的cookie中,仅保存一个 无意义的加密串(与用户名、密码等敏感数据无关),然后在db中保存该加密串-用户信息的对应关系,自动登录 时,用cookie中的加密串,到db中验证,如果通过,自动登录才算通过。

持久化remember me信息

创建一张表,注意这张表的名称和字段都是固定的,不要修改。

CREATE TABLE `persistent_logins` (
`username` varchar(64) NOT NULL,
`series` varchar(64) NOT NULL,
`token` varchar(64) NOT NULL,
`last_used` timestamp NOT NULL,
PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

然后将spring-security.xml中 改为:

<!--
开启remember me过滤器,
data-source-ref="dataSource" 指定数据库连接池
token-validity-seconds="60" 设置token存储时间为60秒 可省略
remember-me-parameter="remember-me" 指定记住的参数名 可省略
-->
<security:remember-me data-source-ref="dataSource"
token-validity-seconds="60" remember-me-parameter="remember-me"/>

最后测试发现数据库中自动多了一条记录:

image-20200919220254094

显示当前认证信息

在header.jsp中找到页面头部最右侧图片处添加如下信息:

<span class="hidden-xs"><security:authentication property="principal.username" />
</span>
或者
<span class="hidden-xs"><security:authentication property="name" />
</span>

授权准备工作

为了模拟授权操作,咱们临时编写两个业务功能:处理器代码:

image-20200920084345762

aside.jsp页面:

image-20200920084406261

动态展示菜单

在aside.jsp对每个菜单通过SpringSecurity标签库指定访问所需角色

image-20200920084933415

image-20200920084945102

image-20200920084959631

我们做个测试,xiaozhi这个用户现在只有普通用户角色ROLE_USER,用xiaozhi登录后,果然只看到了订单管理:

image-20200920085153413

那么问题来了,是不是现在已经授权成功了呢?答案是否定的!你可以试试直接去访问产品的http请求地址:

image-20200920085214629

我们发现xiaozhi其实是可以操作产品模块的,只是没有把产品功能展示给xiaozhi而已!

总结一句:页面动态菜单的展示只是为了用户体验,并未真正控制权限!

授权操作

IOC容器介绍

image-20200920092132700

从这里我们就可以知道,我们的spring-security.xml需要放到父容器中被保护起来,不能放到子容器中被直接访问

说明:SpringSecurity可以通过注解的方式来控制类或者方法的访问权限。注解需要对应的注解支持,若注解放在 controller类中,对应注解支持应该放在mvc配置文件中,因为controller类是有mvc配置文件扫描并创建的,同 理,注解放在service类中,对应注解支持应该放在spring配置文件中。由于我们现在是模拟业务操作,并没有 service业务代码,所以就把注解放在controller类中了。

开启授权的注解支持

这里给大家演示三类注解,但实际开发中,用一类即可!

<!--
开启权限控制注解支持
jsr250-annotations="enabled"    表示支持jsr250-api的注解,需要jsr250-api的jar包
pre-post-annotations="enabled"  表示支持spring表达式注解
secured-annotations="enabled"   这才是SpringSecurity提供的注解
-->
<security:global-method-security jsr250-annotations="enabled"
pre-post-annotations="enabled"
secured-annotations="enabled"/>

在注解支持对应类或者方法上添加注解

image-20200920093528937

image-20200920093540583

我们也可以使用多种注解的方式

@Controller
@RequestMapping("/product")
public class ProductController {//@Secured({"ROLE_PRODUCT","ROLE_ADMIN"})//springSecurity内部制定的注解//@RolesAllowed({"ROLE_PRODUCT","ROLE_ADMIN"})//jsr250注解@PreAuthorize("hasAnyAuthority('ROLE_PRODUCT','ROLE_ADMIN')")//spring的el表达式注解@RequestMapping("/findAll")public String findAll(){return "product-list";}
}

权限不足异常处理

大家也发现了,每次权限不足都出现403页面,着实难堪!体会一下:

image-20200920093821600

用户体验不是很好,现在我们立马消灭它!

image-20200920094756860

方式一:在spring-security.xml配置文件中处理

<!--设置可以用spring的el表达式配置Spring Security并自动生成对应配置组件(过滤器)-->
<security:http auto-config="true" use-expressions="true">
<!--省略其它配置-->
<!--403异常处理-->
<security:access-denied-handler error-page="/403.jsp"/>
</security:http>

方式二:在web.xml中处理

<error-page><error-code>403</error-code><location>/403.jsp</location>
</error-page>

方式三:编写异常处理器

拦截器和过滤器的区别

  • 拦截器:可以在Spring中进行使用
  • 过滤器:只能在web.xml中进行配置,也就是只能在web工程中使用

或者我们可以实现一个Spring给我们提供好的接口

@Component
public class HandlerControllerException implements HandlerExceptionResolver {/*** @param httpServletRequest* @param httpServletResponse* @param o  出现异常的对象* @param e  出现的异常信息* @return   ModelAndView*/@Overridepublic ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {ModelAndView mv = new ModelAndView();//将异常信息放入request域中,基本不用mv.addObject("errorMsg", e.getMessage());//指定不同异常跳转的页面if(e instanceof AccessDeniedException){mv.setViewName("redirect:/403.jsp");}else {mv.setViewName("redirect:/500.jsp");}return mv;}
}

下面一个更简单的方式,通过注解就相当于我们实现了 HandlerExceptionResolver

@ControllerAdvice
public class HandlerControllerAdvice{@ExceptionHandler(AccessDeniedException.class)public String handlerException(){return "redirect:/403.jsp";}@ExceptionHandler(RuntimeException.class)public String runtimeHandlerException(){return "redirect:/500.jsp";}
}

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

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

相关文章

Java数组二:数组的使用

for-each循环 打印数组所有元素 public class Demo04 {public static void main(String[] args) {int[] num {1,5,2,3,4};for (int num1:num) {System.out.println(num1);}} }多维数组 多维数组可以看成是数组的数组&#xff0c;比如二维数组就是一个特殊的一维数组&#x…

JAVA EE初阶 - 预备知识(一)

一、管道 在计算机编程和操作系统环境中&#xff0c;输入、输出和错误管道是用于在不同进程或程序之间传递数据和信息的重要机制&#xff0c;下面分别对它们进行详细介绍&#xff1a; 输入管道&#xff08;Standard Input&#xff0c;stdin&#xff09; 定义&#xff1a;输入…

STM32HAL库快速入门教程——常用外设学习(2)

目录 一、STM32HAL库开发&#xff08;8&#xff09;——CubeMX配置DMA 1.1、什么是DMA&#xff1f; 1.2、内存内存之间的传输&#xff08;单次&#xff09; ​编辑 1.3、内存外设之间的传输&#xff08;ADC&#xff09; 二、STM32HAL库开发&#xff08;9&#xff09;——…

Spring Boot 整合 SSE(Server-Sent Events)

1、简述 SSE&#xff08;Server-Sent Events&#xff09;是一种基于HTTP协议的单向通信机制&#xff0c;允许服务器向浏览器持续发送实时更新。与WebSocket不同&#xff0c;SSE更简单&#xff0c;使用HTTP/1.1协议即可&#xff0c;不需要额外的协议升级。 SSE的特点&#xff…

汽车ECU实现数据安全存储的一种方案

一、 综述 在车辆ECU中总是有一些密钥或重要数据需进行机密性保护&#xff0c;但因产品选型、成本等考虑&#xff0c;导致一些ECU的芯片不支持硬件安全模块&#xff08;例如HSM、TEE等&#xff09;。此时&#xff0c;为保障数据的机密性&#xff0c;可考虑通过软件实现数据的安…

十进制数到十六进制数的转换

十进制数x&#xff0c;若能表示为&#xff0c;n为大于等于0的整数。ni4j。i取值为0、1、2和3。综合i和j&#xff0c;若i为0&#xff0c;则该16进制数为1后面加j个0&#xff1b;若i为1&#xff0c;则该16进制数为2后面加j个0&#xff1b;若i为2&#xff0c;则该16进制数为4后面加…

基于YoloV11+PaddleOCR的车牌检测系统

文章目录 一、CCPD数据集进行处理1.1 从文件夹构建txt格式数据集1.2 运行脚本按照8&#xff1a;2划分训练集&#xff0c;测试集 二 、YOLOV11训练模型2.1 编写car_plate.yaml文件2.2 编写train脚本&#xff1a;2.3 训练过程 三、PaddleOCR识别车牌号3.1 安装paddleocr&#xff…

2月12日鸿蒙生态日日新PLOG,多款应用上架

2月12日鸿蒙生态日日新PLOG &#xff1a;北京医院挂号通、有度、远光商旅等多款应用上架&#xff1b;钉钉、得到、航班管家等多款重点应用功能更新。 ​​​

Python----PyQt开发(PyQt高级:手搓一个简单的记事本)

一、效果展示 二、设计PyQt界面 2.1、设置图标 self.setWindowIcon(QIcon(./images/icon/1.png)) # 窗口图标 2.2、设置标题 self.file_name 无标题-新建文本文档 # 默认文件名 self.setWindowTitle(self.file_name) # 窗口标题 2.3、添加菜单栏、工具栏、状态栏 # 创…

Java 大视界 -- 大数据伦理与法律:Java 技术在合规中的作用与挑战(87)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

什么是AI Agent、Chat、RAG、MoE

什么是AI Agent、Chat、RAG、MoE 目录 什么是AI Agent、Chat、RAG、MoE定义与原理功能特点应用场景AI Agent有哪些关键组成部分感知模块决策模块知识模块行动模块学习模块AI Agent、Chat、RAG、MoE是人工智能领域中不同的概念和技术,它们在功能、原理和应用等方面存在一些区别…

在 debian 12 上安装 mysqlclient 报错

报错如下 Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting mysqlclientUsing cached https://pypi.tuna.tsinghua.edu.cn/packages/61/68/810093cb579daae426794bbd9d88aa830fae296e85172d18cb0f0e5dd4bc/mysqlclient-2.2.7.tar.gz (91 kB)Installi…

自反馈与流量震荡:从 TCP/IP 路由到交通导航

为什么不能基于流量或时延做路由度量&#xff0c;而不仅仅基于跳数。原因在于这里存在一个自反馈&#xff1a; 路由决策导致流量变化&#xff1b;时延由流量变化而变化&#xff1b;流量时延影响路由决策。 当某条链路流量减少时&#xff0c;路由协议会将其度量调低&#xff0…

Jtti:centos主机如何搭建lnmp环境

在 CentOS 主机上搭建 LNMP(Linux Nginx MySQL/MariaDB PHP)环境是构建高性能 Web 服务器的常见选择。以下是搭建 LNMP 环境的详细步骤&#xff1a; 步骤 1: 更新系统 首先&#xff0c;更新系统的包列表和安装的包&#xff0c;以确保你的系统是最新的&#xff1a; sudo y…

如果需要保护多个域名怎么办?

随着企业和个人在网上的存在越来越重要&#xff0c;管理和保护多个域名变得尤为关键&#xff0c;那么如果需要保护这些域名&#xff0c;应该采取什么样的措施呢&#xff1f; 许多企业会选择注册与其品牌相关的不同后缀&#xff0c;或者与其产品、服务相关的域名。这不仅可以防…

从Sora到有言:3D视频生成技术的突破与应用

近年来&#xff0c;AIGC领域飞速发展&#xff0c;这个词也越来越高频地出现在了大家的生活中。AIGC 能完成的任务也越来越多&#xff0c;大模型的能力飞速增长 —— 从Deepseek生成文字&#xff0c;到StableDiffusion生成图像&#xff0c;再到Sora可以生成视频。 而现在&#x…

Apollo 9.0 控制算法 -- lon based pid controller

文章目录 1. 纵向控制算法1.1 算法结构1.1.1 外环&#xff1a;位置环1.1.2 内环&#xff1a;速度环 1.2 参数整定 2. 代码解析2.1 控制器初始化 LonController::Init()2.1.1 PID控制参数和标定表参数加载2.1.2 PID控制器初始化2.1.3 超前/滞后控制器初始化2.1.4 俯仰角滤波器初…

【JavaScript】《JavaScript高级程序设计 (第4版) 》笔记-Chapter12-BOM

十二、BOM 虽然 ECMAScript 把浏览器对象模型&#xff08;BOM&#xff0c;Browser Object Model&#xff09;描述为 JavaScript 的核心&#xff0c;但实际上 BOM 是使用 JavaScript 开发 Web 应用程序的核心。BOM 提供了与网页无关的浏览器功能对象。 HTML5 规范中有一部分涵盖…

Qt信号槽调用出错:Qt: Dead lock detected while activating a BlockingQueuedConnection

目录 1.现象和原因分析 2. 总结 1.现象和原因分析 就在最近的开发过程中&#xff0c;程序一运行在控制台就打印&#xff1a; Qt: Dead lock detected while activating a BlockingQueuedConnection&#xff1a; 咋一看&#xff0c;怎么出现死锁了呢&#xff1f;仔细看下…

Jenkins项目CICD流程

Jenkins项目流程:1.配置git环境 git config --...2.把前后端的目录初始化位本地工作目录 #git init3.提交到本地git #git add ./ git commit -m "" git tag v14.然后提交到远程git(通过,用户,群组,项目,管理项目)git remote add origin http://...git push -…