java每日精进1.31(SpringSecurity)

在所有的开发的系统中,都必须做认证(authentication)和授权(authorization),以保证系统的安全性。

一、基础使用

1.依赖

<dependencies><!-- 实现对 Spring MVC 的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 实现对 Spring Security 的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency></dependencies>

2.application.yml

spring:# Spring Security 配置项,对应 SecurityProperties 配置类security:# 配置默认的 InMemoryUserDetailsManager 的用户账号与密码。user:name: user # 账号password: user # 密码roles: ADMIN # 拥有角色

3.Controller

@RestController
@RequestMapping("/admin")
public class AdminController {@GetMapping("/demo")public String demo() {return "success!";}}

项目启动成功后,浏览器访问 http://127.0.0.1:8080/admin/demo 接口。因为未登录,所以被 Spring Security 拦截到登录界面。

因为我们没有自定义登录界面,所以默认会使用  DefaultLoginPageGeneratingFilter  类,生成上述界面。

登录完成后,因为 Spring Security 会记录被拦截的访问地址,所以浏览器自动动跳转返回界面;

二、自定义规则(自定义 Spring Security 的配置,实现权限控制。)

1.SecurityConfig

创建 SecurityConfig 配置类,继承 WebSecurityConfigurerAdapter 抽象类,实现 Spring Security 在 Web 场景下的自定义配置。代码如下:

// SecurityConfig.java@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {// ...}

重写 #configure(AuthenticationManagerBuilder auth) 方法,实现 AuthenticationManager 认证管理器。

// SecurityConfig.java@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.//使用内存中的 InMemoryUserDetailsManagerinMemoryAuthentication()//不使用 PasswordEncoder 密码编码器.passwordEncoder(NoOpPasswordEncoder.getInstance())//  配置 admin 用户.withUser("admin").password("admin").roles("ADMIN")// 配置 normal 用户.and().withUser("normal").password("normal").roles("NORMAL");
}

重写 #configure(HttpSecurity http) 方法,主要配置 URL 的权限控制。代码如下:

// SecurityConfig.java@Override
protected void configure(HttpSecurity http) throws Exception {http// <X> 配置请求地址的权限.authorizeRequests().antMatchers("/test/echo").permitAll() // 所有用户可访问.antMatchers("/test/admin").hasRole("ADMIN") // 需要 ADMIN 角色.antMatchers("/test/normal").access("hasRole('ROLE_NORMAL')") // 需要 NORMAL 角色。// 任何请求,访问的用户都需要经过认证.anyRequest().authenticated().and()// <Y> 设置 Form 表单登录.formLogin()
//                    .loginPage("/login") // 登录 URL 地址.permitAll() // 所有用户可访问.and()// 配置退出相关.logout()
//                    .logoutUrl("/logout") // 退出 URL 地址.permitAll(); // 所有用户可访问
}

调用 HttpSecurity#authorizeRequests() 方法,开始配置 URL 的权限控制。注意看艿艿配置的四个权限控制的配置。下面,是配置权限控制会使用到的方法:

  • #(String... antPatterns) 方法,配置匹配的 URL 地址,可传入多个。
  • 【常用】#permitAll() 方法,所有用户可访问。
  • 【常用】#denyAll() 方法,所有用户不可访问。
  • 【常用】#authenticated() 方法,登录用户可访问。
  • #anonymous() 方法,无需登录,即匿名用户可访问。
  • #rememberMe() 方法,通过remember me  登录的用户可访问。
  • #fullyAuthenticated() 方法,非remember me 登录的用户可访问。
  • #hasIpAddress(String ipaddressExpression) 方法,来自指定 IP 表达式的用户可访问。
  • 【常用】#hasRole(String role) 方法, 拥有指定角色的用户可访问。
  • 【常用】#hasAnyRole(String... roles) 方法,拥有指定任一角色的用户可访问。
  • 【常用】#hasAuthority(String authority) 方法,拥有指定权限(authority)的用户可访问。
  • 【常用】#hasAuthority(String... authorities) 方法,拥有指定任一权限(authority)的用户可访问。
  • 【最牛】#access(String attribute) 方法,执行结果为 true 时,可以访问。

2.Controller

@RestController
@RequestMapping("/test")
public class TestController {@GetMapping("/echo")public String demo() {return "示例返回";}@GetMapping("/home")public String home() {return "我是首页";}@GetMapping("/admin")public String admin() {return "我是管理员";}@GetMapping("/normal")public String normal() {return "我是普通用户";}}
  • 对于 /test/echo 接口,直接访问,无需登录。
  • 对于 /test/home 接口,无法直接访问,需要进行登录。
  • 对于 /test/admin 接口,需要登录「admin/admin」用户,因为需要 ADMIN 角色。
  • 对于 /test/normal 接口,需要登录「normal/normal」用户,因为需要 NORMAL 角色。

3.Spring Security 的注解,实现权限控制

1.修改权限配置类 

修该 security config 配置类,增加 @EnableGlobalMethodSecurity 注解,开启对 Spring Security 注解的方法,进行权限验证。代码如下:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter

然后即可添加方法级别的权限验证

@PreAuthorize("hasRole('ROLE_NORMAL')")@GetMapping("/normal")public String normal() {return "我是普通用户";}

三、Spring Session

Session 的一致性,简单来理解,就是相同 sessionid 在多个 Web 容器下,Session 的数据要一致。

我们先以用户使用浏览器,Web 服务器为单台 TomcatA 举例子。

  • 浏览器在第一次访问 Web 服务器 TomcatA 时,TomcatA 会发现请求的 Cookie 中存在 sessionid ,所以创建一个 sessionid 为 X 的 Session ,同时将该 sessionid 写回给浏览器的 Cookie 中。
  • 浏览器在下一次访问 Web 服务器 TomcatA 时,TomcatA 会发现请求的 Cookie 中存在 sessionid 为 X ,则直接获得 X 对应的 Session 。

但是如果情况如下:

  • 浏览器访问 TomcatA ,获得 sessionid 为 X 。同时,在多台 Tomcat 的情况下,我们需要采用 Nginx 做负载均衡。
  • 浏览器又发起一次请求访问 Web 服务器,Nginx 负载均衡转发请求到 TomcatB 上。TomcatB 会发现请求的 Cookie 中存在 sessionid 为 X ,则直接获得 X 对应的 Session 。结果呢,找不到 X 对应的 Session ,只好创建一个 sessionid 为 X 的 Session 。
  • 此时,虽然说浏览器的 sessionid 是 X ,但是对应到两个 Tomcat 中两个 Session 。那么,如果在 TomcatA 上做的 Session 修改,TomcatB 的 Session 还是原样,这样就会出现 Session 不一致的问题。

三种解决方案:

第一种,Session 黏连

使用 Nginx 实现会话黏连,将相同 sessionid 的浏览器所发起的请求,转发到同一台服务器。这样,就不会存在多个 Web 服务器创建多个 Session 的情况,也就不会发生 Session 不一致的问题。

不过,这种方式目前基本不被采用。因为,如果一台服务器重启,那么会导致转发到这个服务器上的 Session 全部丢失。

第二种,Session 复制

Web 服务器之间,进行 Session 复制同步。仅仅适用于实现 Session 复制的 Web 容器,例如说 Tomcat 、Weblogic 等等。

不过,这种方式目前基本也不被采用。试想一下,如果我们有 5 台 Web 服务器,所有的 Session 都要同步到每一个节点上,一个是效率低,一个是浪费内存。

第三种,Session 外部化存储

不同于上述的两种方案,Session 外部化存储,考虑不再采用 Web 容器的内存中存储 Session ,而是将 Session 存储外部化,持久化到 MySQL、Redis、MongoDB 等等数据库中。这样,Tomcat 就可以无状态化,专注提供 Web 服务或者 API 接口,未来拓展扩容也变得更加容易。

而实现 Session 外部化存储也有两种方式:

① 基于 Tomcat、Jetty 等 Web 容器自带的拓展,使用读取外部存储器的 Session 管理器。例如说:tomcat 使用 Redis 存储 Session 、实现 Jetty 使用 MySQL、MongoDB 存储 Session 。

② 基于应用层封装 HttpServletRequest 请求对象,包装成自己的 RequestWrapper 对象,从而让实现调用 HttpServletRequest#getSession() 方法时,获得读写外部存储器的 SessionWrapper 对象。

依赖:

<dependencies><!-- 实现对 Spring MVC 的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 实现对 Spring Session 使用 Redis 作为数据源的自动化配置 --><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency><!-- 实现对 Spring Data Redis 的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><exclusions><!-- 去掉对 Lettuce 的依赖,因为 Spring Boot 优先使用 Lettuce 作为 Redis 客户端 --><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><!-- 引入 Jedis 的依赖,这样 Spring Boot 实现对 Jedis 的自动化配置 --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency><!-- 实现对 Spring Security 的自动化配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency></dependencies>

配置文件:

spring:# 对应 RedisProperties 类redis:host: 127.0.0.1port: 6379password: # Redis 服务器密码,默认为空。生产中,一定要设置 Redis 密码!database: 0 # Redis 数据库号,默认为 0 。timeout: 0 # Redis 连接超时时间,单位:毫秒。# 对应 RedisProperties.Jedis 内部类jedis:pool:max-active: 8 # 连接池最大连接数,默认为 8 。使用负数表示没有限制。max-idle: 8 # 默认连接数最大空闲的连接数,默认为 8 。使用负数表示没有限制。min-idle: 0 # 默认连接池最小空闲的连接数,默认为 0 。允许设置 0 和 正数。max-wait: -1 # 连接池最大阻塞等待时间,单位:毫秒。默认为 -1 ,表示不限制。# 对应 SecurityProperties 类security:user: # 配置内存中,可登录的用户名和密码name: nihaopassword: nihao

SessionConfiguration:

@Configuration
@EnableRedisHttpSession // 自动化配置 Spring Session 使用 Redis 作为数据源
public class SessionConfiguration {}

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

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

相关文章

简单的SQL语句的快速复习

语法的执行顺序 select 4 字段列表 from 1 表名列表 where 2 条件列表 group by 3 分组前过滤 having 分组后过滤 order by 5 排序字段列表 limit 6 分页参数 聚合函数 count 统计数量 max 最大值 min 最小值 avg 平均 sum 总和 分组查询使…

《程序人生》工作2年感悟

一些杂七杂八的感悟&#xff1a; 1.把事做好比什么都重要&#xff0c; 先树立量良好的形象&#xff0c;再横向发展。 2.职场就是人情世故&#xff0c;但也不要被人情世故绑架。 3.要常怀感恩的心&#xff0c;要记住帮助过你的人&#xff0c;愿意和你分享的人&#xff0c;有能力…

17.2 图形绘制8

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 17.2.10 重绘 先看以下例子&#xff1a; 【例 17.28】【项目&#xff1a;code17-028】绘制填充矩形。 private void button1_Clic…

自定义数据集 使用pytorch框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测,对预测结果计算精确度和召回率及F1分数

import numpy as np import torch import torch.nn as nn import torch.optim as optim from sklearn.metrics import precision_score, recall_score, f1_score# 数据准备 class1_points np.array([[1.9, 1.2],[1.5, 2.1],[1.9, 0.5],[1.5, 0.9],[0.9, 1.2],[1.1, 1.7],[1.4,…

neo4j入门

文章目录 neo4j版本说明部署安装Mac部署docker部署 neo4j web工具使用数据结构图数据库VS关系数据库 neo4j neo4j官网Neo4j是用ava实现的开源NoSQL图数据库。Neo4作为图数据库中的代表产品&#xff0c;已经在众多的行业项目中进行了应用&#xff0c;如&#xff1a;网络管理&am…

脚本运行禁止:npm 无法加载文件,因为在此系统上禁止运行脚本

问题与处理策略 1、问题描述 npm install -D tailwindcss执行上述指令&#xff0c;报如下错误 npm : 无法加载文件 D:\nodejs\npm.ps1&#xff0c;因为在此系统上禁止运行脚本。 有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_…

Java基础——分层解耦——IOC和DI入门

目录 三层架构 Controller Service Dao ​编辑 调用过程 面向接口编程 分层解耦 耦合 内聚 软件设计原则 控制反转 依赖注入 Bean对象 如何将类产生的对象交给IOC容器管理&#xff1f; 容器怎样才能提供依赖的bean对象呢&#xff1f; 三层架构 Controller 控制…

智慧园区系统集成解决方案引领未来城市管理的智能化转型

内容概要 在现代城市管理的背景下&#xff0c;“智慧园区系统集成解决方案”正扮演着越来越重要的角色。这种解决方案不仅仅是技术上的创新&#xff0c;更是一种全新的管理理念&#xff0c;它旨在通过高效的数据整合与分析&#xff0c;优化资源配置&#xff0c;提升运营效率。…

99.24 金融难点通俗解释:MLF(中期借贷便利)vs LPR(贷款市场报价利率)

目录 0. 承前1. 什么是MLF&#xff1f;1.1 专业解释1.2 通俗解释1.3 MLF的三个关键点&#xff1a; 2. 什么是LPR&#xff1f;2.1 专业解释2.2 通俗解释2.3 LPR的三个关键点&#xff1a; 3. MLF和LPR的关系4. 传导机制4.1 第一步&#xff1a;央行调整MLF4.2 第二步&#xff1a;银…

【VM】VirtualBox安装CentOS8虚拟机

阅读本文前&#xff0c;请先根据 VirtualBox软件安装教程 安装VirtualBox虚拟机软件。 1. 下载centos8系统iso镜像 可以去两个地方下载&#xff0c;推荐跟随本文的操作用阿里云的镜像 centos官网&#xff1a;https://www.centos.org/download/阿里云镜像&#xff1a;http://…

Elasticsearch中的度量聚合:深度解析与实战应用

在大数据和实时分析日益重要的今天&#xff0c;Elasticsearch以其强大的搜索和聚合能力&#xff0c;成为了众多企业和开发者进行数据分析和处理的首选工具。本文将深入探讨Elasticsearch中的度量聚合&#xff08;Metric Aggregations&#xff09;&#xff0c;展示其如何在数据分…

C_C++输入输出(下)

C_C输入输出&#xff08;下&#xff09; 用两次循环的问题&#xff1a; 1.一次循环决定打印几行&#xff0c;一次循环决定打印几项 cin是>> cout是<< 字典序是根据字符在字母表中的顺序来比较和排列字符串的&#xff08;字典序的大小就是字符串的大小&#xff09;…

电脑要使用cuda需要进行什么配置

在电脑上使用CUDA&#xff08;NVIDIA的并行计算平台和API&#xff09;&#xff0c;需要进行以下配置和准备&#xff1a; 1. 检查NVIDIA显卡支持 确保你的电脑拥有支持CUDA的NVIDIA显卡。 可以在NVIDIA官方CUDA支持显卡列表中查看显卡型号是否支持CUDA。 2. 安装NVIDIA显卡驱动…

深入解析:一个简单的浮动布局 HTML 示例

深入解析&#xff1a;一个简单的浮动布局 HTML 示例 示例代码解析代码结构分析1. HTML 结构2. CSS 样式 核心功能解析1. 浮动布局&#xff08;Float&#xff09;2. 清除浮动&#xff08;Clear&#xff09;3. 其他样式 效果展示代码优化与扩展总结 在网页设计中&#xff0c;浮动…

家居EDI:Hom Furniture EDI需求分析

HOM Furniture 是一家成立于1977年的美国家具零售商&#xff0c;总部位于明尼苏达州。公司致力于提供高品质、时尚的家具和家居用品&#xff0c;满足各种家庭和办公需求。HOM Furniture 以广泛的产品线和优质的客户服务在市场上赢得了良好的口碑。公司经营的产品包括卧室、客厅…

【VUE案例练习】前端vue2+element-ui,后端nodo+express实现‘‘文件上传/删除‘‘功能

近期在做跟毕业设计相关的数据后台管理系统&#xff0c;其中的列表项展示有图片展示&#xff0c;添加/编辑功能有文件上传。 “文件上传/删除”也是我们平时开发会遇到的一个功能&#xff0c;这里分享个人的实现过程&#xff0c;与大家交流谈论~ 一、准备工作 本次案例使用的…

C++中的析构器(Destructor)(也称为析构函数)

在C中&#xff0c;析构器&#xff08;Destructor&#xff09;也称为析构函数&#xff0c;它是一种特殊的成员函数&#xff0c;用于在对象销毁时进行资源清理工作。以下是关于C析构器的详细介绍&#xff1a; 析构函数的特点 名称与类名相同&#xff0c;但前面有一个波浪号 ~&a…

VLN视觉语言导航基础

0 概述 视觉语言导航模型旨在构建导航决策模型 π π π&#xff0c;在 t t t时刻&#xff0c;模型能够根据指令 W W W、历史轨迹 τ { V 1 , V 2 , . . . , V t − 1 } \tau\{V_1,V_2,...,V_{t-1}\} τ{V1​,V2​,...,Vt−1​}和当前观察 V t { P t , R t , N ( V t ) } V_…

AI协助探索AI新构型的自动化创新概念

训练AI自生成输出模块化代码&#xff0c;生成元代码级别的AI功能单元代码&#xff0c;然后再由AI组织为另一个AI&#xff0c;实现AI开发AI的能力&#xff1b;用AI协助探索迭代新构型AI将会出现&#xff0c;并成为一种新的技术路线潮流。 有限结点&#xff0c;无限的连接形式&a…

Flux的三步炼丹炉——fluxgym(三):矩阵测试

前面两篇文章给大家介绍了如何准备素材和怎么炼丹&#xff0c;现在我们拿到训练完成后的多个Lora怎么才能确定哪个才是我们需要的、效果最好的呢&#xff1f;答案就是使用xyz图表测试&#xff0c;也称为矩阵测试&#xff0c;通过控制控制变量的方法对Lora模型批量生图&#xff…