【JavaWeb】你这么厉害,知道RBAC权限模型和ABAC权限模型吗?

2023-10-28 05:40

本文主要是介绍【JavaWeb】你这么厉害,知道RBAC权限模型和ABAC权限模型吗?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一.RBAC 权限模型
    • 1.RBAC的组成
    • 2.RBAC模型分类
      • 2.1.基本模型RBAC0
      • 2.2.角色分层模型RBAC1
      • 2.3.角色限制模型RBAC2
      • 2.4.统一模型RBAC3
    • 3.RBAC0模型核心表结构
      • 3.1.表结构设计
      • 3.2.模块划分
    • 4.基于RBAC的延展—用户组
  • 二.ABAC权限模型(基于Java讲解)
    • 1.ABAC是什么
    • 2.ABAC的条件判断控制
    • 3.表达式语言(EL)
    • 4.ABAC实践
      • 4.1.数据库设计
      • 4.2.引入依赖
      • 4.3.修改配置
      • 4.4.CRUD代码
      • 4.5.security上下文
      • 4.6.启动类
      • 4.7.测试类
    • 5.Spring Security 和 Apache Shiro整合

权限在日常系统中算是一个比较常见的基本功能,对于存在有权限模块的系统中规定了登录用户能够操作哪些资源,不能够操作哪些资源。借助权限模块可以有效的控制系统不同身份人员要具体做的操作,可以说一个成熟的后端系统离不开一个比较完善的权限管理系统。

所以权限控制系统的目标就是:管理用户行为,保护系统功能。

那么如何进行权限控制呢?

  • 定义资源
  • 创建权限
  • 创建角色
  • 管理用户
  • 建立关联关系

一.RBAC 权限模型

1.RBAC的组成

  • 在RBAC模型里面,有3个基础组成部分,分别是:用户、角色和权限
    在这里插入图片描述
  • User(用户):每个用户都有唯一的UID识别,并被授予不同的角色
  • Role(角色):不同角色具有不同的权限
  • Permission(权限):访问权限
  • 用户-角色映射:用户和角色之间的映射关系
  • 角色-权限映射:角色和权限之间的映射

    角色权限关系

    • 权限→资源:单向多对多 一个权限可以包含多个资源,一个资源可以被分配给多个不同权限
    • 角色→权限:单向多对多 一个角色可以包含多个权限,一个权限可以被分配给多个不同角色
    • 用户→角色:双向多对多 一个角色可以包含多个用户,一个用户可以身兼数职

如管理员和普通用户被授予不同的权限,普通用户只能去修改和查看个人信息,而不能创建用户和冻结用户,而管理员由于被授予所有权限,所以可以做所有操作。
在这里插入图片描述

2.RBAC模型分类

2.1.基本模型RBAC0

RBAC0是基础,很多系统只需基于RBAC0就可以搭建权限模型了。

  • 在这个模型中,我们把权限赋予角色,再把角色赋予用户。用户和角色,角色和权限都是多对多的关系。用户拥有的权限等于他所有的角色持有权限之和。
    在这里插入图片描述

举个栗子:

  • 譬如我们做一款企业管理产品,可以抽象出几个角色,譬如销售经理、财务经理、市场经理等,然后把权限分配给这些角色,再把角色赋予用户。这样无论是分配权限还是以后的修改权限,只需要修改用户和角色的关系,或角色和权限的关系即可,更加灵活方便。
  • 此外,如果一个用户有多个角色,老王既负责销售部也负责市场部,那么可以给王先生赋予2个角色,即销售经理、市场经理,这样他就拥有这两个角色的所有权限

2.2.角色分层模型RBAC1

RBAC1建立在RBAC0基础之上,在角色中引入了 "继承" 的概念。简单理解就是,给角色可以分成几个等级,每个等级权限不同,从而实现更细粒度的权限管理
在这里插入图片描述
举个栗子:

  • 基于之前RBAC0的例子,我们又发现一个公司的销售经理可能是分几个等级的,譬如除了销售经理,还有销售副经理,而销售副经理只有销售经理的部分权限。这时候,我们就可以采用RBAC1的分级模型,把销售经理这个角色分成多个等级,给销售副经理赋予较低的等级即可。

2.3.角色限制模型RBAC2

RBAC2同样建立在RBAC0基础之上,仅是对用户、角色和权限三者之间增加了一些限制。

  • 这些限制可以分成两类,即静态职责分离SSD(Static Separation of Duty)和动态职责分离DSD(Dynamic Separation of Duty)。具体限制如下图:
    在这里插入图片描述

举个栗子:

  • 还是基于之前RBAC0的例子,我们又发现有些角色之间是需要互斥
    • 譬如给一个用户分配了销售经理的角色,就不能给他再赋予财务经理的角色了,否则他即可以录入合同又能自己审核合同
      • 再譬如,有些公司对角色的升级十分看重,一个销售员要想升级到销售经理,必须先升级到销售主管,这时候就要采用先决条件限制了。

2.4.统一模型RBAC3

RBAC3是RBAC1和RBAC2的合集,所以RBAC3既有**角色分层,也包括可以增加各种限制。**
在这里插入图片描述

3.RBAC0模型核心表结构

3.1.表结构设计

  • 从上面实体对应关系分析,权限表设计分为以下基本的5张表结构:用户表(t_user),角色表(t_role),t_user_role(用户角色表),资源表(t_module),权限表(t_permission),表结构关系如下:
    在这里插入图片描述
t_user	用户表			主键	id	int(11)	自增	主键iduser_name	varchar(20)	非空	用户名user_pwd	varchar(100)	非空	用户密码true_name	varchar(20)	可空	真实姓名email	varchar(30)	可空	邮箱phone	varchar(20)	可空	电话is_valid	int(4)	可空	有效状态create_date	datetime	可空	创建时间update_date	datetime	可空	更新时间t_role	角色表			主键	id	int(11)	自增	主键idrole_name	varchar(20)	非空	角色名role_remarker	varchar(100)	可空	角色备注is_valid	int(4)	可空	有效状态create_date	datetime	可空	创建时间t_user_role	用户角色表			主键	id	int(11)	自增	主键iduser_id	int(4)	非空	用户idrole_id	int(4)	角色id	角色idcreate_date	datetime	可空	创建时间update_date	datetime	可空	更新时间t_module	资源表			主键	id	int(11)	自增	资源idmodule_name	varchar(20)	可空	资源名module_style	varchar(100)	可空	资源样式url	varchar(20)	可空	资源url地址parent_id	int(11)	非空	上级资源idparent_opt_value	varchar(20)	非空	上级资源权限码grade	int(11)	非空	层级opt_value	varchar(30)	可空	权限码orders	int(11)	非空	排序号is_valid	int(4)	可空	有效状态create_date	datetime	可空	创建时间update_date	datetime	可空	更新时间t_permission	权限表			主键	id	int(11)	自增	主键idrole_id	int(11)	非空	角色idmodule_id	int(11)	非空	资源idacl_value	varchar(20)	非空	权限码create_date	datetime	可空	创建时间update_date	datetime	可空	更新时间

3.2.模块划分

从表结构设计可以看出:这里有三张主表(t_user,t_role,t_module),功能实现上这里划分为三大模块:

用户管理

  • 用户基本信息维护
  • 用户角色分配

角色管理

  • 角色基本信息维护
  • 角色授权(给角色分配能够操作的菜单)
  • 角色认证(给角色拥有的权限进行校验)

资源管理

  • 资源信息维护
  • 菜单输出动态控制

4.基于RBAC的延展—用户组

  • 基于RBAC模型,还可以适当延展,使其更适合我们的产品。譬如增加用户组概念,直接给用户组分配角色,再把用户加入用户组。这样用户除了拥有自身的权限外,还拥有了所属用户组的所有权限。
    在这里插入图片描述
    举个栗子:

  • 譬如,我们可以把一个部门看成一个用户组,如销售部,财务部,再给这个部门直接赋予角色,使部门拥有部门权限,这样这个部门的所有用户都有了部门权限。用户组概念可以更方便的给群体用户授权,且不影响用户本来就拥有的角色权限`。

二.ABAC权限模型(基于Java讲解)

1.ABAC是什么

ABAC(Attribute Base Access Control)

  • 基于 属性的权限控制不同于常见的将用户通过某种方式关联到权限的方式,ABAC则是通过动态计算一个或一组属性来是否满足某种条件来进行授权判断(可以编写简单的逻辑)。
  • 属性通常来说分为四类:用户属性(如用户年龄)环境属性(如当前时间)操作属性(如读取)和对象属性,所以理论上能够实现非常灵活的权限控制,几乎能满足所有类型的需求。

2.ABAC的条件判断控制

基于ABAC访问控制需要动态计算实体的属性、操作类型、相关的环境来控制是否有对操作对象的权限,所以在设计的时候需要考虑的条件判断的灵活性、通用性、易用性,用户只需要通过web页面即可配置授权,这需要减少硬编码似得逻辑变得简单通用,那么这需要满足一些运算符来实现。

类型运算符
算术运算符+, -, *, /, %, ^, div, mod
关系运算符<, >, ==, !=, <=, >=, lt, gt, eq, ne, le, ge
逻辑运算符and, or, not, &&,
条件?:
  • 举个栗子: 用户只需要配置 user.age > 20 的条件即可获得特定的权限。

3.表达式语言(EL)

正如上一节所说的需要对某种条件进行解析那么就需要表达式语言,使用表达式语言可以方便的访问对象中的属性、或是进行各种数学运算,条件判断等

正如:Spring Framework的@Value注解和MyBatis的<if test=“”>

// 相信很多 Java boy都使用过的吧
@Value("A?B:C")
private String A;
<select id = "XXX"><if test="user != null">XXXX</if>
</select

此ABAC的的核心就是Expression Language(EL),虽然演示是Java使用作为演示,但是其他的编程语言都是有着自己的EL框架的。

java EL框架列表

  • spring-expression

  • OGNL

  • MVEL

  • JBoss EL

感兴趣可以查看 Java EL生态排名:https://mvnrepository.com/open-source/expression-languages

4.ABAC实践

4.1.数据库设计

在这里插入图片描述
在这里插入图片描述

# 用户表
DROP TABLE IF EXISTS USER;
CREATE TABLE USER (id BIGINT(20) NOT NULL COMMENT '主键ID',NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年龄',email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (id) COMMENT '用户表'
);
# 用户边缘数据
DROP TABLE IF EXISTS user_contribution;
CREATE TABLE user_contribution (id BIGINT(20) NOT NULL COMMENT '主键ID',user_id BIGINT(20)  NOT NULL COMMENT '用户表ID',repository VARCHAR(100) NOT NULL COMMENT '仓库',PRIMARY KEY (id) COMMENT '用户边缘数据'
);
# 权限表
DROP TABLE IF EXISTS permission;
CREATE TABLE permission (id BIGINT(20) NOT NULL COMMENT '主键ID',permission VARCHAR(100) NOT NULL COMMENT '权限名称',PRIMARY KEY (id) COMMENT '权限表'
);
# abac表达式表
DROP TABLE IF EXISTS abac;
CREATE TABLE abac (id BIGINT(20) NOT NULL COMMENT '主键ID',expression VARCHAR(100) NOT NULL COMMENT 'abac表达式',PRIMARY KEY (id) COMMENT 'abac表达式表'
);
# abac表和权限表的关联表, o2m
DROP TABLE IF EXISTS abac_permission;
CREATE TABLE abac_permission (id BIGINT(20) NOT NULL COMMENT '主键ID',abac_id BIGINT(20) NOT NULL COMMENT 'abac表ID',permission_id BIGINT(20) NOT NULL COMMENT 'permission表ID',PRIMARY KEY (id) COMMENT 'abac表和权限表的关联表, o2m'
);#插入用户数据
DELETE FROM USER;
INSERT INTO USER (id, NAME, age, email)
VALUES (1, '魏昌进', 26, 'mail@wcj.plus'),(2, 'test', 1, 'mail1@wcj.plus'),(3, 'admin', 1, 'mail2@wcj.plus');#插入用户边缘数据
DELETE FROM user_contribution;
INSERT INTO user_contribution (id, user_id, repository)
VALUES (1, 1, 'galaxy-sea/spring-cloud-apisix'),(2, 2, 'spring-cloud/spring-cloud-commons'),(3, 2, 'spring-cloud/spring-cloud-openfeign'),(4, 2, 'alibaba/spring-cloud-alibaba'),(5, 2, 'Tencent/spring-cloud-tencent'),(6, 2, 'apache/apisix-docker');#插入权限数据
DELETE FROM permission;
INSERT INTO permission (id, permission)
VALUES (1, 'github:pr:merge'),(2, 'github:pr:close'),(3, 'github:pr:open'),(4, 'github:pr:comment');#插入abac表达式数据 
DELETE FROM abac;
INSERT INTO abac (id, expression)
VALUES (1, 'contributions.contains(''galaxy-sea/spring-cloud-apisix'')'),(2, 'name == ''admin'''),(3, 'metadata.get(''ip'') == ''192.168.0.1''');#插入abac表达式-权限映射关系数据  
DELETE FROM abac_permission;
INSERT INTO abac_permission (id, abac_id, permission_id)
VALUES (1, 1, 1),(2, 2, 1),(3, 2, 2),(4, 2, 3),(5, 2, 4),(6, 3, 1),(7, 3, 2),(8, 3, 3),(9, 3, 4);

4.2.引入依赖

本章仅实现ABAC的原理,不会对Spring Security和 Apache Shiro做任何的集成

框架

  • Java 8
  • Spring Boot 2.x
  • MyBatis Plus 3.5.x
  • MySQL 8.0
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.5.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>abac</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot-abac</name><description>springboot-abac</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.2</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>compile</scope></dependency><!-- security权限依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

4.3.修改配置

spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:password: rootusername: rootdriver-class-name: com.mysql.cj.jdbc.Driver#数据库名字自己定义url: jdbc:mysql://127.0.0.1:3306/abac_test?serverTimezone=UTC&useUnicode=true&charaterEncoding=utf-8&useSSL=falsevalidation-query: SELECT 1mybatis-plus:#配置 Maaper xml文件所在路径mapper-locations: classpath*:/mapper/**/*.xml#配置映射类所在的包名type-aliases-package: com.example.entityserver:port: 8090

4.4.CRUD代码

entiy

@Data
public class Abac {private Long id;private String expression;/*** expression对应的permissions列表*/@TableField(exist = false)private List<String> permissions;
}
@Data
public class User {private Long id;private String name;private Integer age;private String email;/** 用户提交过仓库 */@TableField(exist = false)private List<String> contributions = new ArrayList<>();/** 存放一些乱七八糟的数据,当然contributions字段也放在这里 */@TableField(exist = false)private Map<String, Object> metadata = new HashMap<>();
}

dao层

@Mapper
public interface AbacDao extends BaseMapper<Abac> {/** 获取abacId关联权限 */@Select("SELECT p.permission\n" +"FROM abac_permission ap LEFT JOIN permission p ON p.id = ap.permission_id\n" +"WHERE ap.abac_id = #{abacId}")List<String> selectPermissions(Long abacId);
}
@Mapper
public interface UserDao extends BaseMapper<User> {/** 获取用户的仓库信息 */@Select("SELECT repository FROM user_contribution WHERE user_id = #{userId}")List<String> selectRepository(@Param("userId") Long userId);
}

service层

@Service
@RequiredArgsConstructor
public class AbacService {private final AbacDao abacDao;/** 获取abac表达式详细信息列表 */public List<Abac> getAll() {List<Abac> abacs = abacDao.selectList(null);for (Abac abac : abacs) {List<String> permissions = abacDao.selectPermissions(abac.getId());abac.setPermissions(permissions);}return abacs;}
}
@Service
@RequiredArgsConstructor
public class UserService {private final UserDao userDao;/** 根据userId获取用户详细信息 */public User get(Long userId) {User user = userDao.selectById(userId);List<String> repository = userDao.selectRepository(userId);user.setContributions(repository);return user;}
}

4.5.security上下文

/*** 自定义用户元数据  用于获取一些实体的属性、操作类型、相关的环境*/
public interface MetadataCustomizer {/** 自定义用户元数据 */void customize(User user);
}
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;/*** 解析abac表达式*/
@Component
public class SecurityContext {/*** SpEL表达式解析器*/private final ExpressionParser expressionParser = new SpelExpressionParser();/*** 解析abac表达式** @param user  用户详细信息* @param abacs abac表达式详细信息集合* @return expressions集合, 将这个结果集存放到 Spring Security 或者Apache APISIX的userDetail上下文中*/public List<String> rbacPermissions(User user, List<Abac> abacs) {return this.rbacPermissions(user, abacs, Collections.emptyList());}/*** 解析abac表达式** @param user                用户详细信息* @param abacs               abac表达式详细信息集合* @param metadataCustomizers 自定义用户元数据  用于获取一些实体的属性、操作类型、相关的环境* @return expressions集合, 将这个结果集存放到 Spring Security 或者Apache APISIX的userDetail上下文中*/public List<String> rbacPermissions(User user, List<Abac> abacs, List<MetadataCustomizer> metadataCustomizers) {// 处理自定义元数据metadataCustomizers.forEach(metadataCustomizer -> metadataCustomizer.customize(user));List<String> expressions = new ArrayList<>();for (Abac abac : abacs) {// 解析表达式的求值器Expression expression = expressionParser.parseExpression(abac.getExpression());// 创建环境上下文EvaluationContext context = new StandardEvaluationContext(user);// 获取expression的结果if (expression.getValue(context, boolean.class)) {expressions.addAll(abac.getPermissions());}}return expressions;}
}

4.6.启动类

@SpringBootApplication
public class SpringbootAbacApplication {public static void main(String[] args) {SpringApplication.run(SpringbootAbacApplication.class, args);}
}

4.7.测试类

@SpringBootTest
class AbacApplicationTests {@Autowiredprivate UserService userService;@Autowiredprivate AbacService abacService;@Autowiredprivate SecurityContext securityContext;/** 获取不同用户的abac权限 */@Testvoid testRbac() {User user = userService.get(1L);System.out.println(user);List<Abac> rbac = abacService.getAll();System.out.println(rbac);List<String> permissions = securityContext.rbacPermissions(user, rbac);System.out.println(permissions);user = userService.get(2L);System.out.println(user);permissions = securityContext.rbacPermissions(user, rbac);System.out.println(permissions);user = userService.get(3L);System.out.println(user);permissions = securityContext.rbacPermissions(user, rbac);System.out.println(permissions);}/*** 获取自定义权限*/@Testvoid testMetadataCustomizer() {User user = userService.get(1L);System.out.println(user);List<Abac> rbac = abacService.getAll();System.out.println(rbac);List<String> permissions = securityContext.rbacPermissions(user, rbac);System.out.println(permissions);permissions = securityContext.rbacPermissions(user, rbac, getMetadataCustomizer());System.out.println(permissions);}/** 模拟网络ip */private List<MetadataCustomizer> getMetadataCustomizer() {return new ArrayList<MetadataCustomizer>() {{add(user -> user.getMetadata().put("ip", "192.168.0.1"));}};}
}

testRbac()测试效果

#用户1
User(id=1, name=魏昌进, age=26, email=mail@wcj.plus, contributions=[galaxy-sea/spring-cloud-apisix], metadata={})
#所有ABAC
[Abac(id=1, expression=contributions.contains('galaxy-sea/spring-cloud-apisix'), permissions=[github:pr:merge]), Abac(id=2, expression=name == 'admin', permissions=[github:pr:merge, github:pr:close, github:pr:open, github:pr:comment]), Abac(id=3, expression=metadata.get('ip') == '192.168.0.1', permissions=[github:pr:merge, github:pr:close, github:pr:open, github:pr:comment])]
#用户1权限
[github:pr:merge]#用户2
User(id=2, name=test, age=1, email=mail1@wcj.plus, contributions=[spring-cloud/spring-cloud-commons, spring-cloud/spring-cloud-openfeign, alibaba/spring-cloud-alibaba, Tencent/spring-cloud-tencent, apache/apisix-docker], metadata={})
#用户2权限
[]#用户3
User(id=3, name=admin, age=1, email=mail2@wcj.plus, contributions=[], metadata={})
#用户3权限
[github:pr:merge, github:pr:close, github:pr:open, github:pr:comment]

testMetadataCustomizer()测试效果

#用户1
User(id=1, name=魏昌进, age=26, email=mail@wcj.plus, contributions=[galaxy-sea/spring-cloud-apisix], metadata={})
#所有ABAC
[Abac(id=1, expression=contributions.contains('galaxy-sea/spring-cloud-apisix'), permissions=[github:pr:merge]), Abac(id=2, expression=name == 'admin', permissions=[github:pr:merge, github:pr:close, github:pr:open, github:pr:comment]), Abac(id=3, expression=metadata.get('ip') == '192.168.0.1', permissions=[github:pr:merge, github:pr:close, github:pr:open, github:pr:comment])]
#解析abac表达式,获取用户1满足条件的权限
[github:pr:merge]
#自定义用户元数据 ,判断用户1是否满足ip环境权限
[github:pr:merge, github:pr:merge, github:pr:close, github:pr:open, github:pr:comment]

5.Spring Security 和 Apache Shiro整合

Spring Security只需要修改拦截器即可在获取到UserDetailsSecurityContext#rbacPermissions转换为GrantedAuthority即可

/*** 这里是伪代码, 展示一下大概逻辑*/
public class IamOncePerRequestFilter implements OncePerRequestFilter {@Autowiredprivate SecurityContext securityContext;@Autowiredprivate AbacService abacService;@Autowiredprivate List<MetadataCustomizer> metadataCustomizers;@Autowiredpublic void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {UserDetails user = toUser();List<String> permissions = securityContext.rbacPermissions(user, abacService.getAll(), metadataCustomizers);List<GrantedAuthority> abacAuthority = permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());user.getAuthorities().addAll(abacAuthority);}
}

这篇关于【JavaWeb】你这么厉害,知道RBAC权限模型和ABAC权限模型吗?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/291052

相关文章

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja

springboot项目中整合高德地图的实践

《springboot项目中整合高德地图的实践》:本文主要介绍springboot项目中整合高德地图的实践,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一:高德开放平台的使用二:创建数据库(我是用的是mysql)三:Springboot所需的依赖(根据你的需求再

spring中的ImportSelector接口示例详解

《spring中的ImportSelector接口示例详解》Spring的ImportSelector接口用于动态选择配置类,实现条件化和模块化配置,关键方法selectImports根据注解信息返回... 目录一、核心作用二、关键方法三、扩展功能四、使用示例五、工作原理六、应用场景七、自定义实现Impor

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志

《SpringBoot项目配置logback-spring.xml屏蔽特定路径的日志》在SpringBoot项目中,使用logback-spring.xml配置屏蔽特定路径的日志有两种常用方式,文中的... 目录方案一:基础配置(直接关闭目标路径日志)方案二:结合 Spring Profile 按环境屏蔽关

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.