Spring Security
一.权限控制
1.1 认证和授权概念
问题1:在生产环境下我们如果不登录后台系统就可以完成这
些功能操作吗?
答案显然是否定的,要操作这些功能必须首先登录到系统才可
以。
问题2:是不是所有用户,只要登录成功就都可以操作所有功
能呢?
答案是否定的,并不是所有的用户都可以操作这些功能。不同
的用户可能拥有不同的权限,这就需要进行授权了。
认证:系统提供的用于识别用户身份的功能,通常提供用户名
和密码进行登录其实就是在进行认证,认证的目的是让系统知
道你是谁。
授权:用户认证成功后,需要为用户授权,其实就是指定当前
用户可以操作哪些功能。
1.2 权限模块数据模型
前面已经分析了认证和授权的概念,要实现最终的权限控制,
需要有一套表结构支撑:
用户表t_user、权限表t_permission、角色表t_role、菜单表
t_menu、用户角色关系表t_user_role、角色权限关系表
t_role_permission、角色菜单关系表t_role_menu。
表之间关系如下图:
通过上图可以看到,权限模块共涉及到7张表。在这7张表
中,角色表起到了至关重要的作用,其处于核心位置,因为用
户、权限、菜单都和角色是多对多关系。
接下来我们可以分析一下在认证和授权过程中分别会使用到哪
些表:
授权过程:用户必须完成认证之后才可以进行授权,首先可以
根据用户查询其角色,再根据角色查询对应的菜单,这样就确
定了用户能够看到哪些菜单。然后再根据用户的角色查询对应
的权限,这样就确定了用户拥有哪些权限。所以授权过程会用
到上面7张表。
1.3 Spring Security简介
Spring Security是 Spring提供的安全认证服务的框架。使用
Spring Security可以帮助我们来简化认证和授权的过程。
常用的权限框架除了Spring Security,还有Apache的shiro框
架。
二.Spring Security入门案例
2.1 工程搭建
创建maven工程,打包方式为war。提供index.html页面,内
容为hello Spring Security!!
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/
4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>demo01</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging><dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.1.5.RELEASE</version>
</dependency><dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>5.1.5.RELEASE</version>
</dependency><dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.6.RELEASE</version>
</dependency><dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency></dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-
plugin</artifactId>
<configuration>
<!-- 指定端口 -->
<port>8080</port>
<!-- 请求路径 -->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.2 配置web.xml
在web.xml中主要配置SpringMVC的DispatcherServlet和用
于整合第三方框架的DelegatingFilterProxy,用于整合Spring
Security。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/
javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener><context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-security.xml</param-value>
</context-param><filter>
<!--
DelegatingFilterProxy用于整合第三方框架
整合Spring Security时过滤器的名称必须为
springSecurityFilterChain,
否则会抛出NoSuchBeanDefinitionException
异常
-->
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter><filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
2.3 配置spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">
<!--
auto-config:是否自动配置
设置为true时框架会提供默认的一些配
置,例如提供默认的登录页面、登出处理等
设置为false时需要显示提供登录表单配
置,否则会报错
use-expressions:是否使用spring
security提供的表达式来描述权限
-->
<security:http auto-config="true" use-
expressions="true">
<!--
intercept-url:定义一个拦截规则
pattern:描述拦截规则 /** 表示拦截
所有请求
asscess:指定所需的访问角色或者访问权
限
-->
<security:intercept-url
pattern="/**" access="hasAnyRole('ROLE_ADMIN')">
</security:intercept-url>
</security:http>
<!--配置认证管理器-->
<security:authentication-manager>
<!--配置认证提供者-->
<security:authentication-provider>
<!-- 配置一个具体的用户,后期需要从数
据库查询用户-->
<security:user-service>
<security:user name="admin"
password="{noop}123456"
authorities="ROLE_ADMIN"></security:user>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>
2.4 入门案例改进
前面我们已经完成了Spring Security的入门案例,通过入门案
例我们可以看到,Spring Security将我们项目中的所有资源都
保护了起来,要访问这些资源必须要完成认证而且需要具有
ROLE_ADMIN角色。但是入门案例中的使用方法离我们真实
生产环境还差很远,还存在如下一些问题:
*项目中我们将所有的资源(所有请求URL)都保护起来,
实际环境下往往有一些资源不需要认证也可以访问,也就
是可以匿名访问。
* 登录页面是由框架生成的,而我们的项目往往会使用自己
的登录页面。
*直接将用户名和密码配置在了配置文件中,而真实生产环
境下用户名和密码往往保存在数据库中
*在配置文件中配置的密码使用明文,这非常不安全,而真
实生产环境下密码需要进行加密。
三.案例改进
3.1 配置可匿名访问的资源
第一步:在项目中创建pages目录,在pages目录中创建
a.html和b.html
第二步:在spring-security.xml文件中配置,指定哪些资源可
以匿名访问
第三步:通过上面的配置可以发现,pages目录下的文件可以
在没有认证的情况下任意访问。
<!--
配置哪些资源匿名可以访问(不登录也可以访
问)
指定哪些资源不需要进行权限校验,可以使用通
配符
-->
<!-- <security:http security="none"
pattern="/pages/a.html"></security:http>-->
<!-- <security:http security="none"
pattern="/pages/b.html"></security:http>-->
<security:http security="none"
pattern="/pages/**"></security:http>
3.2 使用指定的登录页面
第一步:提供login.html作为项目的登录页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<h3>自定义登录页面</h3>
<form action="/login" method="post">
username:<input type="text"name="username"><br>
password:<input type="password"name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
第二步:修改spring-security.xml文件,指定login.html页
面可以匿名访问
<security:http security="none" pattern="/login.html" />
第三步:修改spring-security.xml文件,加入表单登录信
息的配置
<security:http auto-config="true" use-expressions="true">
<!--
intercept-url:定义一个拦截规则
pattern:描述拦截规则 /** 表示拦截
所有请求
asscess:指定所需的访问角色或者访问权
限
-->
<security:intercept-url
pattern="/**" access="hasAnyRole('ROLE_ADMIN')">
</security:intercept-url>
<!--
如果我们要使用自己指定的页面作为登录页面,
必须配置登录表单.页面提交的登录表单请求是由框架负责处理
login-page:指定登录页面访问URL
-->
<security:form-login
login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login"
default-target-url="/index.html"
authentication-failure-url="/login.html"></security:form-login>
<!--
csrf:对应CsrfFilter过滤器
disabled:是否启用CsrfFilter过滤
器,如果使用自定义登录页面需要关闭此项,否则登录操作会被禁
用(403)
-->
<security:csrf disabled="true">
</security:csrf>
</security:http>
3.3 从数据库查询用户信息
如果我们要从数据库动态查询用户信息,就必须按照spring
security框架的要求提供一个实现UserDetailsService接口的
实现类,并按照框架的要求进行配置即可。框架会自动调用实
现类中的方法并自动进行密码校验。
实体类:
public class Emp {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
实现类:
public class EmpService implements
UserDetailsService {
public Map<String, Emp> map=new HashMap<>
();//模拟数据库中的数据
public void initData(){
Emp emp1=new Emp();
emp1.setUsername("admin");
emp1.setPassword("123456");
Emp emp2=new Emp();
emp2.setUsername("xiaoming");
emp2.setPassword("123456");
map.put(emp1.getUsername(),emp1);
map.put(emp2.getUsername(),emp2);
}
@Override
public UserDetails loadUserByUsername(String
username) throws UsernameNotFoundException {
initData();
System.out.println("username="+username);
Emp emp = map.get(username);//模拟根据用户名查询员工信息
if(emp==null){
//用户不存在
return null;
}else{
//将用户信息返回给框架
//框架会进行密码比对(页面提交的密码和数据库查询的密码进行比对)
List<GrantedAuthority> list=new
ArrayList<>();
//为当前用户授权 后期需要改为从数据库查询当前用户对应的权限
list.add(new
SimpleGrantedAuthority("permission_A"));//授权
list.add(new
SimpleGrantedAuthority("permission_B"));//授权
if(username.equals("admin")){
list.add(new
SimpleGrantedAuthority("ROLE_ADMIN"));//授予角色
}
User securityUser=new
User(username,"{noop}"+emp.getPassword(),list);
return securityUser;
}
}
}
spring-security.xml:
<!--配置认证管理器-->
<security:authentication-manager>
<!--配置认证提供者-->
<security:authentication-provider
user-service-ref="empService">
<!-- 配置一个具体的用户,后期需要从数
据库查询用户-->
<!-- <security:user-service>-->
<!-- <security:user
name="admin" password="{noop}123456"
authorities="ROLE_ADMIN"></security:user>-->
<!-- </security:user-service>-->
</security:authentication-provider>
</security:authentication-manager>
<bean id="empService" class="com.lzw.service.EmpService"></bean>
我们提供了UserService实现类,并且按照框架的要求实现了
UserDetailsService接口。在spring配置文件中注册
UserService,指定其作为认证过程中根据用户名查询用户信
息的处理类。当我们进行登录操作时,spring security框架会
调用UserService的loadUserByUsername方法查询用户信
息,并根据此方法中提供的密码和用户页面输入的密码进行比
对来实现认证操作。
3.4 对密码加密
前面我们使用的密码都是明文的,这是非常不安全的。一般情
况下用户的密码需要进行加密后再保存到数据库中。
常见的密码加密方式有:
3DES、AES、DES:使用对称加密算法,可以通过解密来还原
出原始密码
MD5、SHA1:使用单向HASH算法,无法通过计算还原出原
始密码,但是可以建立彩虹表进行查表破解
bcrypt:将salt随机并混入最终加密后的密码,验证时也无需
单独提供之前的salt,从而无需单独处理salt问题
加密后的格式一般为:
第一步:在spring-security.xml文件中指定密码加密对象、
<!--配置认证管理器-->
<security:authentication-manager>
<!--配置认证提供者-->
<security:authentication-provider
user-service-ref="empService">
<!-- 配置一个具体的用户,后期需要从数
据库查询用户-->
<!-- <security:user-service>-->
<!-- <security:user
name="admin" password="{noop}123456"
authorities="ROLE_ADMIN"></security:user>-->
<!-- </security:user-service>-->
<!--指定度密码进行加密的对象-->
<security:password-encoder ref="passwordEncoder"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<bean id="empService"class="com.lzw.service.EmpService"></bean>
<!--配置密码加密对象-->
<bean id="passwordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<!--开启spring注解使用-->
<context:annotation-config>
</context:annotation-config>
第二步:修改UserService实现类
public class EmpService implements
UserDetailsService {
@Autowired
private BCryptPasswordEncoder
passwordEncoder;
public Map<String, Emp> map=new HashMap<>
();//模拟数据库中的数据
public void initData(){
Emp emp1=new Emp();
emp1.setUsername("admin");
emp1.setPassword(passwordEncoder.encode("123456"
));
Emp emp2=new Emp();
emp2.setUsername("xiaoming");
emp1.setPassword(passwordEncoder.encode("123456"
));
map.put(emp1.getUsername(),emp1);
map.put(emp2.getUsername(),emp2);
}
@Override
public UserDetails loadUserByUsername(String
username) throws UsernameNotFoundException {
initData();
System.out.println("username="+username);
Emp emp = map.get(username);//模拟根据用户名查询员工信息
if(emp==null){
//用户不存在
return null;
}else{
//将用户信息返回给框架
//框架会进行密码比对(页面提交的密码和数据库查询的密码进行比对)
List<GrantedAuthority> list=new
ArrayList<>();
//为当前用户授权 后期需要改为从数据库查询当前用户对应的权限
list.add(new
SimpleGrantedAuthority("permission_A"));//授权
list.add(new
SimpleGrantedAuthority("permission_B"));//授权
if(username.equals("admin")){
list.add(new
SimpleGrantedAuthority("ROLE_ADMIN"));//授予角色
}
User securityUser=new
User(username,emp.getPassword(),list);
return securityUser;
}
}
}
3.5 配置多种校验规则
为了测试方便,首先在项目中创建a.html、b.html、c.html、
d.html几个页面
修改spring-security.xml文件:
<security:http auto-config="true" use-expressions="true">
<!--
intercept-url:定义一个拦截规则
pattern:描述拦截规则 /** 表示拦截
所有请求
asscess:指定所需的访问角色或者访问权
限
-->
<!--只要认证通过就可以访问-->
<security:intercept-url
pattern="/pages/a.html"access="isAuthenticated()" />
<!--拥有add权限就可以访问b.html页面-->
<security:intercept-url
pattern="/pages/b.html"access="hasAuthority('add')" />
<!--拥有ROLE_ADMIN角色就可以访问c.html
页面-->
<security:intercept-url
pattern="/pages/c.html"
access="hasRole('ROLE_ADMIN')" />
<!--拥有ROLE_ADMIN角色就可以访问d.html
页面,
注意:此处虽然写的是ADMIN角色,框架会
自动加上前缀ROLE_-->
<security:intercept-url
pattern="/pages/d.html"
access="hasRole('ADMIN')" />
<security:intercept-url
pattern="/**" access="hasAnyRole('ROLE_ADMIN')">
</security:intercept-url>
<!--
如果我们要使用自己指定的页面作为登录页面,
必须配置登录表单.页面提交的登录表单请求是由框架负责处理
login-page:指定登录页面访问URL
-->
<security:form-login
login-page="/login.html"
username-
parameter="username"
password-
parameter="password"
login-processing-url="/login"
default-target-url="/index.html"
authentication-failure-url="/login.html"></security:form-login>
<!--
csrf:对应CsrfFilter过滤器
disabled:是否启用CsrfFilter过滤
器,如果使用自定义登录页面需要关闭此项,否则登录操作会被禁
用(403)
-->
<security:csrf disabled="true">
</security:csrf>
</security:http>
3.6 注解方式权限控
第一步:在spring-security.xml文件中配置组件扫描,用于扫
描Controller
<!--开启spring注解使用-->
<context:annotation-config></context:annotation-config>
<mvc:annotation-driven></mvc:annotation-driven>
<context:component-scan base-package="com.lzw.controller">
</context:component-scan>
第二步:在spring-security.xml文件中开启权限注解支持
<!--开启注解方式权限控制-->
<security:global-method-security pre-post-annotations="enabled" />
第三步:创建Controller类并在Controller的方法上加入注解
进行权限控制
@RestController
@RequestMapping("/emp")
public class EmpController {
@RequestMapping("/add")
@PreAuthorize("hasAuthority('add')")//表示用户必须拥有add权限才能调用当前方法
public String add(){
System.out.println("add...");
return "success";
}
@RequestMapping("/delete")
@PreAuthorize("hasRole('ROLE_ADMIN')")//表示用户必须拥有ROLE_ADMIN角色才能调用当前方法
public String delete(){
System.out.println("delete...");
return "success";
}
}
3.7 退出登录
用户完成登录后Spring Security框架会记录当前用户认证状态
为已认证状态,即表示用户登录成功了。那用户如何退出登录
呢?我们可以在spring-security.xml文件中进行如下配置:
<security:http auto-config="true" use-expressions="true">
<!--
intercept-url:定义一个拦截规则
pattern:描述拦截规则 /** 表示拦截所有请求
asscess:指定所需的访问角色或者访问权限
-->
<!--只要认证通过就可以访问-->
<security:intercept-url
pattern="/pages/a.html"
access="isAuthenticated()" />
<!--拥有add权限就可以访问b.html页面-->
<security:intercept-url
pattern="/pages/b.html"
access="hasAuthority('add')" />
<!--拥有ROLE_ADMIN角色就可以访问c.html页面-->
<security:intercept-url
pattern="/pages/c.html"
access="hasRole('ROLE_ADMIN')" />
<!--拥有ROLE_ADMIN角色就可以访问d.html页面,
注意:此处虽然写的是ADMIN角色,框架会自动加上前
缀ROLE_-->
<security:intercept-url
pattern="/pages/d.html"
access="hasRole('ADMIN')" />
<security:intercept-url pattern="/**"
access="hasAnyRole('ROLE_ADMIN')">
</security:intercept-url>
<!--
如果我们要使用自己指定的页面作为登录页面,必须配置登
录表单.页面提交的登录表单请求是由框架负责处理
login-page:指定登录页面访问URL
-->
<security:form-login
login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login"
default-target-url="/index.html"
authentication-failure-
url="/login.html"></security:form-login>
<!--
csrf:对应CsrfFilter过滤器
disabled:是否启用CsrfFilter过滤器,如果使用
自定义登录页面需要关闭此项,否则登录操作会被禁用(403)
-->
<security:csrf disabled="true">
</security:csrf>
<!--
logout:退出登录
logout-url:退出登录操作对应的请求路径
logout-success-url:退出登录后的跳转页面
-->
<security:logout logout-url="/logout"
logout-success-
url="/login.html" invalidate-session="true"/>
</security:http>
通过上面的配置可以发现,如果用户要退出登录,只需要请
求/logout.do这个URL地址就可以,同时会将当前session失
效,最后页面会跳转到login.html页面。
相关文章:
Spring Security
一.权限控制 1.1 认证和授权概念 问题1:在生产环境下我们如果不登录后台系统就可以完成这 些功能操作吗? 答案显然是否定的,要操作这些功能必须首先登录到系统才可 以。 问题2:是不是所有用户,只要登录成功就都可以操…...
OpenAI 正式发布 o1 完整版
OpenAI 在 o1 模型完整版,该模型相较于之前的 o1-preview 版本在智能能力上有所提升,特别是在编程能力方面,并且能够根据问题的难度智能调节响应速度。此外还新增了图像识别功能,但目前仍然不支持网页浏览、文件上传等功能 o1 模…...
Ubuntu22.04搭建LAMP环境(linux服务器学习笔记)
目录 引言: 一、系统更新 二、安装搭建Apache2 1.你可以通过以下命令安装它: 2.查看Apache2版本 3.查看Apache2运行状态 4.浏览器访问 三、安装搭建MySQL 1.安装MySQL 2.查看MySQL 版本 3.安全配置MySQL 3.1是否设置密码?(按y|Y表…...
C#与PLC通讯时,数据读取和写入浮点数,字节转换问题(ModbusTCP)
在与PLC进行通讯时,会发现一个问题,浮点数1.2接收过来后,居然变成了两个16位的整数。 经过一系列的分析,这是因为在PLC存储浮点数时32位,我们接收过来的数据会变成两个16位的高低字节,而且我们进行下发数据…...
synchronized的特性
1.互斥 对于synchronized修饰的方法及代码块不同线程想同时进行访问就会互斥。 就比如synchronized修饰代码块时,一个线程进入该代码块就会进行“加锁”。 退出代码块时会进行“解锁”。 当其他线程想要访问被加锁的代码块时,就会阻塞等待。 阻塞等待…...
NLP与LLM的工程化实践与学习思考 - 说说知识图谱
NLP与LLM的工程化实践与学习思考[24年半年工作总结] - 说说知识图谱 0 真的就是先说说1 为什么知识图谱什么是知识图谱?基于图的数据结构?基于数据结构的图?知识图谱的技术要点两个技术维度:知识、图七个技术要点:表示…...
php 系统函数 记录
PHP intval() 函数 PHP函数介绍—array_key_exists(): 检查数组中是否存在特定键名 如何使用PHP中的parse_url函数解析URL PHP is_array()函数详解,PHP判断是否为数组 PHP函数介绍:in_array()函数 strpos定义和用法 strpos() 函数查找字符串在另一字符串…...
游戏引擎学习第38天
仓库: https://gitee.com/mrxiao_com/2d_game 回顾上次的内容。 我们之前讨论了将精灵放在屏幕上,但颜色错误的问题。问题最终查明是因为使用了一个调整工具,导致文件的字节顺序发生了变化。重新运行“image magic”工具对一些大图像进行重新处理后&am…...
Android 15 行为变更:所有应用
Android 15 平台包含一些可能会影响您的应用的行为变更。以下行为变更将影响在 Android 15 上运行的所有应用,无论采用哪种 targetSdkVersion 都不例外。您应该测试您的应用,然后根据需要进行修改,以适当地支持这些变更。 此外,请…...
基于pytorch的深度学习基础4——损失函数和优化器
四.损失函数和优化器 4.1 均值初始化 为减轻梯度消失和梯度爆炸,选择合适的权重初值。 十种初始化方法 Initialization Methods 1. Xavie r均匀分布 2. Xavie r正态分布 4. Kaiming正态分布 5. 均匀分布 6. 正态分布 7. 常数分布 8. 正交矩阵初…...
《Clustering Propagation for Universal Medical Image Segmentation》CVPR2024
摘要 这篇论文介绍了S2VNet,这是一个用于医学图像分割的通用框架,它通过切片到体积的传播(Slice-to-Volume propagation)来统一自动(AMIS)和交互式(IMIS)医学图像分割任务。S2VNet利…...
Webpack Source Map 配置详解与优化策略
前言 Source Map 是前端开发和调试中的核心工具之一,它可以显著提高我们在代码调试和错误追踪方面的效率。随着 JavaScript 应用越来越复杂,代码打包和优化成为必然,而这一过程会使得调试变得异常困难。Source Map 的出现,为我们…...
el-tree组件刷新指定id的节点数据
示例 封装一个可以刷新多个指定id的节点数据。 <template><el-tree ref"treeRef"></el-tree> </template><script lang"ts" setup> const treeRef ref()function refreshTreeById(nodeIds: number[]) {nodeIds.forEach((…...
深入 Java 基础 XML:高级特性与最佳实践
在上一篇文章中,我们对 Java 基础 XML 有了一个初步的认识,了解了 XML 的基本结构以及在 Java 中常见的解析方式。今天,我们将进一步深入探讨 Java 与 XML 的结合,包括一些高级特性和最佳实践。 一、XML 命名空间 在复杂的 XML …...
aws(学习笔记第十六课) 使用负载均衡器(ELB)解耦webserver以及输出ELB的日志到S3
aws(学习笔记第十六课) 使用负载均衡器(ELB)以及输出ELB的日志到S3 学习内容: 使用负载均衡器(ELB)解耦web server输出ELB的日志到S3 1. 使用负载均衡器(ELB) 全体架构 使用ELB(Elastic Load Balancer)能够解耦外部internet访问和web server之间的耦合,…...
Ubuntu与Centos系统有何区别?
Ubuntu和CentOS都是基于Linux内核的操作系统,但它们在设计理念、使用场景和技术实现上有显著的区别。以下是详细的对比: 1. 基础和发行版本 Ubuntu: 基于Debian,使用.deb包管理系统。包含两个主要版本: LTSÿ…...
【OpenDRIVE_Python】使用python脚本读取txt指定内容,输出OpenDRIVE数据中对应的信息
示例代码说明: 读取txt指定内容如地物id,输出OpenDRIVE数据中的对应地物id和名称name信息为xml文件 import xml.dom.minidom from xml.dom.minidom import parse from xml.dom import Node import sys import os # 读取OpenDRIVE文件路径 xml_filepath…...
Qt入门8——Qt文件
1. Qt文件概述 文件操作是应用程序必不可少的部分。Qt作为⼀个通用开发库,提供了跨平台的文件操作能力。Qt 提供了很多关于文件的类,通过这些类能够对文件系统进行操作,如文件读写、文件信息获取、文件复制或重命名等。 2. 输入输出设备类 在…...
【每天一道面试题】JWT是什么?Java-jwt是什么?(2024/12/7)
【每天一道面试题】JWT是什么?Java-jwt是什么?(2024/12/7) JWT:JSON Web Token 俗称令牌 当我们想实现: 1.用户不用输入用户名和密码就可以登录(不用每次都输入用户名和密码) 2.用户的信息在传…...
ORB-SLAM3源码学习:ImuTypes.cc:Eigen::Matrix3f RightJacobianSO3计算右雅可比矩阵
前言 计算右雅可比矩阵这个函数涉及到了函数重载,可以接受不同的参数来实现计算右雅可比矩阵。 代码分析 右雅可比矩阵: /** * brief 计算右雅可比* param xyz 李代数* return Jr*/ Eigen::Matrix3f RightJacobianSO3(const float &x, const fl…...
电子公文交换系统设计 ——基于商用密码标准的密码模块的应用
文章目录 《密码系统设计》实验实验项目实验四 密码模块的应用实践要求(40 分) 《密码系统设计》实验 实验项目 实验序号实验名称实验学时数实验目的实验内容实验类型学生学习预期成果实验四密码模块的应用6基于商用密码标准的密码模块的应用对电子公文…...
java抽象类
目录 一.抽象类 1.什么是抽象类 2.抽象类特点 (1)抽象类不能直接实例化对象 (2)可以包含抽象方法和具体方法 (3)可以有构造方法 (4)抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用 abstract 修…...
渤海证券基于互联网环境的漏洞主动防护方案探索与实践
来源:中国金融电脑 作者:渤海证券股份有限公司信息技术总部 刘洋 伴随互联网业务的蓬勃发展,证券行业成为黑客进行网络攻击的重要目标之一,网络攻击的形式也变得愈发多样且复杂。网络攻击如同悬于行业之上的达摩克利斯之剑&…...
ClouderaManager 集群搭建
前提:服务器之前做过域名映射、免密登录 ClouderaManager 集群 1. 组件分布规划 服务器服务器h1zk、hdfs(dn)、yarn(nm)、spark、kafka、flumeh2hdfs(nn-standy)、yarn(rm-active)、sparkh3hdfs(nn-active)、yarn(rm-standy)、hive、sparkh4zk、hdfs(dn)、yarn(n…...
Nginx部署PHP服务端跨域以及跨域携带cookie
🤵 作者:coderYYY 🧑 个人简介:前端程序媛,目前主攻web前端,后端辅助,其他技术知识也会偶尔分享🍀欢迎和我一起交流!🚀(评论和私信一般会回!!) 👉 个人专栏推荐:《前端项目教程以及代码》 ✨一、前言 前端技术栈Vue+后端技术栈PHP+Mysql鉴权以及存储信息用…...
流量转发利器之Burpsuite概述(1)
目录 一、Burpsuite Burp Suite Spider 的主要特点: 在 Burp Suite 中使用 Spider: Spider 的用例: 限制: 声明:学习视频来自b站up主 泷羽sec,如涉及侵权马上删除文章 声明:本文主要用作技…...
【优选算法 二分查找】二分查找算法入门详解:二分查找小专题
x 的平方根 题目解析 算法原理 解法一: 暴力解法 如果要求一个数(x)的平方根,可以从 0 往后枚举,直到有一个数(a),a^2<x,(a1)^2>x,a即为所求; 解法二:二分查找 …...
LeetCode—56. 合并区间(中等)
题目描述: 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 示例1: 输入&#x…...
SHELL----正则表达式
一、文本搜索工具——grep grep -参数 条件 文件名 其中参数有以下: -i 忽略大小写 -c 统计匹配的行数 -v 取反,不显示匹配的行 -w 匹配单词 -E 等价于 egrep ,即启用扩展正则表达式 -n 显示行号 -rl 将指定目录内的文件打…...
web斗地主游戏实现指北
前后端通信 作为一个即时多人游戏,不论是即时聊天还是更新玩家状态,都需要服务端有主动推送功能,或者客户端轮询。轮询的时间间隔可能导致游玩体验差,因为不即时更新,而且请求数量太多可能会打崩服务器。 建议在cs间…...
ES(elasticsearch)整合Spring boot使用实例
1.1通过docker安装es详细教程参考 docker部署elasticsearch(内涵集群部署的compose文件)-CSDN博客 2.1创建MySQL数据库,通过sql命令进行表的创建与数据的写入(sql命令如下) /*Navicat Premium Data TransferSource Server : localSo…...
创建简单的 PL/pgSQL 存储过程
文章目录 创建简单的 PL/pgSQL 存储过程CREATE OR REPLACE FUNCTIONadd_two_numbers(a integer, b integer)RETURNS integerAS$$ ... $$函数体LANGUAGE plpgsql 创建带有 IN 和 OUT 参数的存储过程创建修改数据的存储过程创建带有异常处理的复杂存储过程 在 PostgreSQL 中&…...
前端路径“@/“的使用和配置
环境:vitets 需要安装types/node npm install types/node --save-dev在tsconfig.json中添加 如果有tsconfig.app.json和tsconfig.node.json文件,则在app.json中添加 "compilerOptions": {"baseUrl":".","paths&q…...
彻底理解ThreadLocal的应用场景和底层实现
一.概念 定义: ThreadLocal 是 Java 中所提供的线程本地存储机制,可以利用该机制将数据缓存在某个线程内部,该线程可以在任意时刻、任意方法中获取缓存的数据。 其实是可以通过调用 Set() 方法往里面存入值,存入的值是每个线程互…...
机器学习(5)无监督模型之降维PCA算法
主成分分析(Principal Component Analysis, PCA) 是一种经典的无监督学习算法,主要用于数据降维、特征提取和数据可视化。它通过线性变换将数据从原始空间映射到一个新的空间,使得数据的方差最大化,从而实现降维。PCA …...
React 组件中 State 的定义、使用及正确更新方式
🌈个人主页:前端青山 🔥系列专栏:React篇 🔖人终将被年少不可得之物困其一生 依旧青山,本期给大家带来React篇专栏内容React 组件中 State 的定义、使用及正确更新方式 前言 在 React 应用开发中,state …...
18 设计模式之迭代器模式(书籍遍历案例)
一、什么是迭代器模式 迭代器模式(Iterator Pattern)是一种行为型设计模式,允许客户端通过统一的接口顺序访问一个集合对象中的元素,而无需暴露集合对象的内部实现。这个模式主要用于访问聚合对象(如集合、数组等&…...
Springboot3介绍
一、Springboot3简介: https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html?spmwolai.workspace.0.0.68b62306Q6jtTw#getting-started.introducing-spring-boot 无论使用XML、注解、Java配置类还是他们的混合用法,配置文件过于…...
【Leetcode Top 100】23. 合并 K 个升序链表
问题背景 给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中,返回合并后的链表。 数据约束 k l i s t s . l e n g t h k lists.length klists.length 0 ≤ k ≤ 1 0 4 0 \le k \le 10^4 0≤k≤104 0 ≤ l i s t s […...
显存和GPU之间的通信;GPUDirect P2P,NVLink,NCCL;聚合通信和点对点通信
目录 显存和GPU之间的分配 显存和GPU之间的通信 原语是什么,简单举例说明 GPUDirect P2P,NVLink,NCCL的全称及解释 聚合通信和点对点通信 聚合通信(Collective Communication) 点对点通信(Point-to-Point Communication) 为什么使用GPUDirect P2P,NVLink,NCCL…...
2412d,d的7月会议
原文 总结 卡斯滕 Carsten说,Decard一直在大量试验WebAssembly.他们一直在把d运行时挖出来,直到它工作.他们在浏览器中运行了一些库函数,并试了不同虚机. 他们在移动方面遇见了很多问题,因为不同芯片按不同方式工作.他们想让他们的整个SDK在WASM上运行,但可能需要一年时间才…...
vue框架
以下是一个简单的基于Vue框架的日历组件示例: <template><div class"calendar"><div class"header"><button click"prevMonth"><</button><h2>{{ currentMonth }}</h2><button cli…...
Django drf基于APIView 快速使用
1. 注册 # settings.pyINSTALLED_APPS [,rest_framework, ]2. 路由 from django.urls import pathurlpatterns [path(task/, views.TaskAPIView.as_view()) ]3. 视图 from rest_framework.views import APIView from rest_framework.response import Responseclass TaskAPIV…...
git commit -m “Add user login feature“
当然,这条命令是 Git 中用来提交更改的基本命令,其中包含了一些注释来解释命令的各个部分。下面是对这条命令的详细解释: git commit -m "-m指的是message,git要求每次提交都需要写一下日志"git commit: 这…...
mac: docker : Command not found解决
描述: 安装docker但是docker命令显示Command not found 分析: mac没有配置对应的环境变量 解决方案: 打开配置文件: vim ~/.zshrc写docker环境变量: export PATH"/Applications/Docker.app/Contents/Resources/bin:$PATH"保存退出: esc,输入wq,按enter 配置文…...
深入解析 HTML Input 元素:构建交互性表单的核心
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
Docker--Docker Registry(镜像仓库)
什么是Docker Registry? 镜像仓库(Docker Registry)是Docker生态系统中用于存储、管理和分发Docker镜像的关键组件。 镜像仓库主要负责存储Docker镜像,这些镜像包含了应用程序及其相关的依赖项和配置,是构建和运行Doc…...
Linux 统信UOS 设置程序“桌面快捷方式”与“开机自启动”
最近在统信uos系统 arm64架构上进行QT程序的开发,基本开发完毕后,开始着手准备程序的开机自启动模块,因为一般来说,程序在客户现场使用都是需要开机自启的。 然后在百度海淘,很少有这类相关的博客介绍,有一…...
React开发高级篇 - React Hooks以及自定义Hooks实现思路
Hooks介绍 Hooks是react16.8以后新增的钩子API; 目的:增加代码的可复用性,逻辑性,弥补无状态组件没有生命周期,没有数据管理状态state的缺陷。 为什么要使用Hooks? 开发友好,可扩展性强&#…...
shell条件测试
一.命令执行结果判定 && 在命令执行后如果没有任何报错时会执行符号后面的动作 || 在命令执行后如果命令有报错会执行符号后的动作 示例: [rootqingdeng shell3]# sh sl.sh /mnt/file is not exist no二.条件判断方法 在 shell 程序中,用户可…...