单点登录三:添加RBAC权限校验模型功能理解及实现demo
1、RBAC权限模型
RBAC(Role-Based Access Control)是一种基于角色的访问控制模型,用于管理系统中用户的权限和访问控制。它将用户、角色和权限之间的关系进行了明确的定义,以实现灵活的权限管理和控制。
1.1、RBAC模型主要包括以下几个核心概念:
1、模型概念:
用户(User):系统中的实际操作者,拥有唯一标识符。
角色(Role):权限的集合,可以被赋予给用户,一个用户可以拥有一个或多个角色。
权限(Permission):系统中的具体操作权限,定义了用户可以执行的操作,可以是功能菜单的接口路径URL,也可以是其他细粒度的操作权限。
2、操作概念:
授权(Authorization):将权限赋予用户或角色的过程,即为用户分配相应的角色或权限。
认证(Authentication):验证用户的身份和权限,确保用户具有访问系统资源的合法权限。
RBAC模型的基本原则是:权限授权应该基于角色,而不是直接授权给特定用户。通过角色的中介,将权限与用户进行解耦,实现了权限的集中管理和灵活分配。
1.2、RBAC模型的优点包括:
- 简化权限管理:通过角色的授权机制,可以集中管理和维护权限,减少了权限管理的复杂性。
- 灵活的权限分配:通过给用户分配适当的角色,可以灵活地控制用户的权限,实现细粒度的访问控制。
- 易于扩展和维护:RBAC模型具有良好的可扩展性和维护性,可以根据业务需求进行权限的增删改操作,而不影响其他部分的权限控制。
在实际应用中,RBAC模型可以结合权限管理框架和安全框架来实现。例如,使用Spring Security框架可以方便地实现RBAC模型的权限控制,通过定义角色、权限和用户的关系,并结合注解和配置来实现权限的校验和访问控制。
总结来说,RBAC模型是一种灵活和可扩展的权限管理模型,通过角色的授权机制实现了权限的集中管理和灵活分配,为系统提供了高效、安全和可维护的访问控制机制。
1.3、RBAC级别
- RBAC0:用户和角色是多对多,角色和权限是多对多。一个用户拥有的权限,是他所有角色的集合。
- RBAC1:基于RBAC0,并引入了角色分层的概念,即一个角色分为多个等级,每个等级对应的权限是不一样的。把权限分给用户时,需要分到对应的角色等级。角色等级低时拥有的权限少,角色等级高的权限是所有角色等级低的权限的集合。
- RBAC2:基于RBAC1,对角色访问进行限制。
- 如互斥角色限制:同一个用户分配到两个角色,且角色互斥时,那么系统应该提醒只能选择其中一个角色。比如员工拥有商务这个角色,可以创建结算单并提交给财务审核,这时,就不能赋予这个员工财务角色,否则他就自己提交结算自己审核结算单了。
- 角色数量限制:一个用户拥有的角色数量是有限的;一个角色被分配的用户数量也是有限的。
- 先决条件限制:用户想获得某个上级角色,必须先获得其下一级的角色。比如想获得产品总监的权限,那就需要从产品助理这一角色开始,再到产品经理角色,最后到产品总监角色。
- RBAC3:基于RBAC0,对RBAC1和RBAC2进行了整合,是最全面的权限管理。
1.4、RBAC模型复杂情况
当用户非常多的情况,可以设计用户组的概念,用户组代替原先用户的概念,这样能起到批量操作用户角色的作用;
权限组的概念也差不多,是权限过多的情况,一个一个赋权操作太繁琐,可以用权限组批量操作,非常方便。
1.5、springSecruity中实际运用简单的步骤
- 用户表、角色表、权限表。然后两张关联表将用户和角色,角色和权限做关联。
- 添加用户的时候,给user特定的用户角色。
- 登录时,将查询用户信息,将角色信息放进token,或缓存(比如redis,外部缓存好处是能临时控制权限)中。
- 登录后的操作,都会经过自定义filter,验证通过的话,可以将用户信息放进springSecruity上下文,和ThreadLocal(这里是因为登录以及验证角色权限是单线程操作,使用本地线程速度最快,比map以及外部缓存都快)。
- 我们想使用权限,而且无侵入的去控制的话,可以弄个自定义注解,参数为角色名,验证ThreadLocal中保存的用户信息中的角色中是否包含此角色名,返回boolean类型。
2、demo实现
结合前面我写的两篇帖子,这里整理了一个demo,能够实现一个简单的无侵入的登录及权限控制方案。这里用到springSecruity、jwt、redis、mysql、threadLocal等技术
0、springboot配置
数据源自己配,就是要提前有redis和mysql
server:port: 8083spring:application:name: playerredis:host: xxxxxxxport: xxxxxxxdatasource:url: jdbc:mysql://xxxxxxx:xxxx/xxxxxxusername: rootpassword: Aa@123456driver-class-name: com.mysql.cj.jdbc.Driverjpa:hibernate:ddl-auto: nonemybatis:mapper-locations: classpath:mappers/*.xmltype-aliases-package: com.loong.nba.player.pojo
1、依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.2</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-impl</artifactId><version>0.11.2</version><scope>runtime</scope></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.2</version><scope>runtime</scope></dependency><!-- MyBatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency><!-- 数据库驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.31</version></dependency>
</dependencies>
2、util
package com.loong.nba.player.util;import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;import java.security.Key;
import java.util.Date;
import java.util.concurrent.TimeUnit;/*** @author jilong* @date 2023/5/18*/
@Component
public class JwtUtil {private final Key secretKey;private final long expirationTime;@Autowiredprivate StringRedisTemplate redisTemplate;public JwtUtil() {this.secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256);this.expirationTime = 120000;}/*** 生成jwt令牌** @param username 用户名* @return token*/public String generateToken(String username) {Date now = new Date();Date expirationDate = new Date(System.currentTimeMillis() + expirationTime);String token = Jwts.builder().setSubject(username).setIssuedAt(now).setExpiration(expirationDate).signWith(secretKey, SignatureAlgorithm.HS256).compact();redisTemplate.opsForValue().set(username, token, expirationTime, TimeUnit.MILLISECONDS);return token;}/*** 解析令牌** @param token token* @return 内容*/public String getUsernameFormToken(String token) {return extractClaims(token).getBody().getSubject();}public boolean validateToken(String token) {try {Jws<Claims> claims = extractClaims(token);return !claims.getBody().getExpiration().before(new Date());} catch (Exception e) {e.printStackTrace();return false;}}private Jws<Claims> extractClaims(String token) {JwtParser parser = Jwts.parserBuilder().setSigningKey(secretKey).build();return parser.parseClaimsJws(token);}
}
package com.loong.nba.player.util;import com.loong.nba.player.pojo.LoginUserBO;public class SessionUtils {static ThreadLocal<LoginUserBO> loginUser = new ThreadLocal<>();public static LoginUserBO getLoginUser() {return loginUser.get();}public static void setLoginUser(LoginUserBO loginUserBO) {loginUser.set(loginUserBO);}
}
3、pojo
package com.loong.nba.player.pojo;public class UserPO {private Integer id;private String username;private String password;private String salt;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}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 String getSalt() {return salt;}public void setSalt(String salt) {this.salt = salt;}
}
package com.loong.nba.player.pojo;import java.util.List;public class LoginUserBO {private String username;private Integer userId;private String password;private List<Role> roleList;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Integer getUserId() {return userId;}public void setUserId(Integer userId) {this.userId = userId;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public List<Role> getRoleList() {return roleList;}public void setRoleList(List<Role> roleList) {this.roleList = roleList;}
}
package com.loong.nba.player.pojo;public class Role {private Integer id;private String roleName;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getRoleName() {return roleName;}public void setRoleName(String roleName) {this.roleName = roleName;}
}
package com.loong.nba.player.pojo;/*** @author jilong* @date 2023/5/19*/
public class UserDO {private String name;private String password;public UserDO() {}public UserDO(String name, String password) {this.name = name;this.password = password;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}
4、config
package com.loong.nba.player.config;import com.loong.nba.player.filter.JwtAuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;/*** @author jilong* @date 2023/5/18*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {private final JwtAuthenticationFilter jwtAuthenticationFilter;public SecurityConfig(JwtAuthenticationFilter jwtAuthenticationFilter) {this.jwtAuthenticationFilter = jwtAuthenticationFilter;}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers("/login","/user").permitAll().anyRequest().authenticated().and().addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class).sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}
5、dao层
package com.loong.nba.player.dao;import com.loong.nba.player.pojo.Role;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface RoleMapper {List<Role> findByUserId(Integer id);}
package com.loong.nba.player.dao;import com.loong.nba.player.pojo.UserPO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;@Mapper
public interface UserMapper {UserPO findById(Integer id);UserPO findByName(@Param("name") String name);Integer addUser(@Param("userPO") UserPO userPO);}
6、service
package com.loong.nba.player.service;import com.loong.nba.player.pojo.UserDO;
import com.loong.nba.player.pojo.UserPO;public interface UserService {/*** 添加用户* @return 用户id*/UserPO addUser(UserDO userDO);boolean comparePassword(UserDO userDO);}
package com.loong.nba.player.service;import com.loong.nba.player.dao.UserMapper;
import com.loong.nba.player.pojo.UserDO;
import com.loong.nba.player.pojo.UserPO;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;/*** @author jilong* @date 2023/5/19*/
@Service
public class UserServiceImpl implements UserService {private final UserMapper userMapper;public UserServiceImpl(UserMapper userMapper) {this.userMapper = userMapper;}@Overridepublic UserPO addUser(UserDO userDO) {// 定义盐的长度(字节数)int saltLength = 6;// 创建一个安全的随机数生成器SecureRandom secureRandom = new SecureRandom();// 生成盐byte[] salt = new byte[saltLength];secureRandom.nextBytes(salt);// 将盐转换为字符串或字节数组String saltString = encodeSalt(salt);// 计算密码摘要String password = encryptPassword(userDO.getPassword(), saltString);UserPO userPO = new UserPO();userPO.setUsername(userDO.getName());userPO.setPassword(password);userPO.setSalt(saltString);userMapper.addUser(userPO);System.out.println("Salt (Base64 string): " + saltString);return userPO;}String encodeSalt(byte[] salt) {return Base64.getEncoder().encodeToString(salt);}byte[] decodeSaltString(String saltString) {return Base64.getDecoder().decode(saltString);}String encryptPassword(String password, String salt) {String plaintext = password + salt;try {// 创建SHA-256算法的MessageDigest实例MessageDigest digest = MessageDigest.getInstance("SHA-256");// 计算中文字符串的摘要byte[] hash = digest.digest(plaintext.getBytes(StandardCharsets.UTF_8));// 将摘要字节数组转换为十六进制字符串表示String digestHex = bytesToHex(hash);System.out.println("SHA-256摘要:" + digestHex);return digestHex;} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return null;}// 将摘要字节数组转换为十六进制字符串表示private static String bytesToHex(byte[] bytes) {StringBuilder hexStringBuilder = new StringBuilder();for (byte b : bytes) {String hex = Integer.toHexString(0xff & b);if (hex.length() == 1) {hexStringBuilder.append('0');}hexStringBuilder.append(hex);}return hexStringBuilder.toString();}@Overridepublic boolean comparePassword(UserDO userDO) {UserPO user = userMapper.findByName(userDO.getName());String salt = user.getSalt();String password = encryptPassword(userDO.getPassword(), salt);return password.equals(user.getPassword());}}
7、filter
package com.loong.nba.player.filter;import com.loong.nba.player.dao.RoleMapper;
import com.loong.nba.player.dao.UserMapper;
import com.loong.nba.player.pojo.LoginUserBO;
import com.loong.nba.player.pojo.Role;
import com.loong.nba.player.pojo.UserPO;
import com.loong.nba.player.util.JwtUtil;
import com.loong.nba.player.util.SessionUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;/*** @author jilong* @date 2023/5/18*/
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {private final String tokenHeader = "Authorization";private final String tokenPrefix = "Bearer ";private final JwtUtil jwtUtil;private final StringRedisTemplate redisTemplate;private final UserMapper userMapper;private final RoleMapper roleMapper;public JwtAuthenticationFilter(JwtUtil jwtUtil, StringRedisTemplate redisTemplate, UserMapper userMapper, RoleMapper roleMapper) {this.jwtUtil = jwtUtil;this.redisTemplate = redisTemplate;this.userMapper = userMapper;this.roleMapper = roleMapper;}@Overridepublic void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {String header = request.getHeader(tokenHeader);if (!ObjectUtils.isEmpty(header) && header.startsWith(tokenPrefix)) {String token = header.replace(tokenPrefix, "");if (!ObjectUtils.isEmpty(token) && jwtUtil.validateToken(token)) {String username = jwtUtil.getUsernameFormToken(token);UserPO userPO = userMapper.findByName(username);List<Role> roleList = roleMapper.findByUserId(userPO.getId());LoginUserBO loginUserBO = new LoginUserBO();loginUserBO.setUserId(userPO.getId());loginUserBO.setUsername(username);loginUserBO.setPassword(userPO.getPassword());loginUserBO.setRoleList(roleList);if (redisTemplate.opsForValue().get(username) != null) {UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, null, Collections.emptyList());SecurityContextHolder.getContext().setAuthentication(authenticationToken);SessionUtils.setLoginUser(loginUserBO);}}}chain.doFilter(request, response);}
}
8、controller
package com.loong.nba.player.controller;import com.loong.nba.player.pojo.UserDO;
import com.loong.nba.player.pojo.UserPO;
import com.loong.nba.player.service.UserServiceImpl;
import com.loong.nba.player.util.JwtUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletResponse;/*** @author jilong* @date 2023/5/15*/
@RestController
public class LoginController {private final JwtUtil jwtUtil;private final UserServiceImpl userService;public LoginController(JwtUtil jwtUtil, UserServiceImpl userService) {this.jwtUtil = jwtUtil;this.userService = userService;}@PostMapping("/login")public ResponseEntity<UserDO> postLogin(@RequestBody UserDO userDO, HttpServletResponse response) {if (!userService.comparePassword(userDO)) {return ResponseEntity.ok(new UserDO());}String token = jwtUtil.generateToken(userDO.getName());response.addHeader("Authorization", "Bearer " + token);return ResponseEntity.ok(userDO);}@PostMapping("/user")public UserPO addUser(@RequestBody UserDO userDO) {return userService.addUser(userDO);}@GetMapping("/test")@PreAuthorize("@permission.hasRole("+"'管理员'"+")")public String test() {return "hello test";}
}
9、mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.loong.nba.player.dao.RoleMapper"><select id="findByUserId" resultType="Role">SELECT role.id , role.rolename FROM role where idIN (SELECT role_id FROM user_role WHERE user_id = #{id})</select></mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.loong.nba.player.dao.UserMapper"><select id="findById" resultType="UserPO">SELECT * FROM user WHERE id = #{id}</select><select id="findByName" resultType="UserPO">SELECT * FROM user WHERE username = #{name}</select><insert id="addUser" parameterType="UserPO">INSERT INTO user (username, user_password, salt)VALUES (#{userPO.username}, #{userPO.password}, #{userPO.salt})</insert>
</mapper>
相关文章:

单点登录三:添加RBAC权限校验模型功能理解及实现demo
1、RBAC权限模型 RBAC(Role-Based Access Control)是一种基于角色的访问控制模型,用于管理系统中用户的权限和访问控制。它将用户、角色和权限之间的关系进行了明确的定义,以实现灵活的权限管理和控制。 1.1、RBAC模型主要包括以…...
基于用户认证数据构建评估模型预测认证行为风险系统(附源码)
文件说明 datasets // 数据集(训练集、测试集) feature engineering // 特征工程 models // 评估模型 测试环境 Python3.8 任务描述 项目来自系统认证风险预测https://www.datafountain.cn/competitions/537 项目完整源码下载:https://download.csdn.net/download/liu…...
本地训练中文LLaMA模型实战教程,民间羊驼模型,24G显存盘它!
羊驼实战系列索引 博文1:本地部署中文LLaMA模型实战教程,民间羊驼模型 博文2:本地训练中文LLaMA模型实战教程,民间羊驼模型(本博客) 博文3:精调训练中文LLaMA模型实战教程,民间羊驼模型(马上发布) 简介 在学习完上篇【1本地部署中文LLaMA模型实战教程,民间羊驼模…...
快速学Go依赖注入工具wire
Go相对java和C是较新的语言,但也有诸多优秀特性及生态库。本文介绍大多数软件工程中常用的功能:依赖注入。首先介绍什么是依赖注入,go实现库wire与其他语言的差异。然后通过简单示例实现依赖注入,简化代码、提升可读性。 依赖注入…...
python入门(4)流程控制语句
1. 条件判断语句 条件控制语句用于根据条件来决定程序的执行路径。在Python中,常见的条件控制语句有以下几种: (1)if语句:用于执行满足条件的代码块。示例代码: age 20 if age > 18:print("成年…...

【进阶】C 语言表驱动法编程原理与实践
数据压倒一切。如果选择了正确的数据结构并把一切组织的井井有条,正确的算法就不言自明。编程的核心是数据结构,而不是算法。——Rob Pike 目录 说明 概念提出 查表方式 直接查找 索引查找 分段查找 实战示例 字符统计 月天校验 名称构造 值名…...

java+springboot留学生新闻资讯网的设计与实现
Spring框架是Java平台的一个开放源代码的Full-stack(全栈)应用程序框架,和控制翻转容器的实现。Spring框架的一些核心功能理论,可以用于所有Java应用,Spring还为Java EE构建的Web应用提供大量的扩展支持。Spring框架没有实现任何的编程模型&a…...
分布式事务与分布式锁区别及概念学习
一、 分布式事务 1.1 背景 传统事务ACID是基于单数据库的本地事务,仅支持单机事务,并不支持跨库事务。但随着微服务架构的普及,业务的分库分表导致一个大型业务系统往往由若干个子系统构成,这些子系统又拥有各自独立的数据库。往往一个业务流程需要由多个子系统共同完成,…...

windows先的conda环境复制到linux环境
如果是迁移的环境一致:同是windows或同是linux直接用这个命令即可: conda create -n new_env_name --clone old_env_path 如果是window的环境迁移到linux这种跨环境就不能用上面的方法,网上这方面的资料也很多,记录一下我的…...

庄懂的TA笔记(十七)<特效:屏幕UV + 屏幕扰动>
庄懂的TA笔记(十七)<特效:屏幕UV 屏幕扰动> 大纲: 目录 庄懂的TA笔记(十七)<特效:屏幕UV 屏幕扰动> 大纲: 正文: 一…...

手写简易RPC框架
目录 简介 服务提供者 服务注册:注册中心 HttpServerHandler处理远程调用请求 consumer服务消费端 简介 RPC(Remote Procedure Call)——远程过程调用,它是一种通过网络从远程计算机程序上请求服务, 而不需要了解…...

基于孪生网络的目标跟踪
一、目标跟踪 目标跟踪是计算机视觉领域研究的一个热点问题,其利用视频或图像序列的上下文信息,对目标的外观和运动信息进行建模,从而对目标运动状态进行预测并标定目标的位置。具体而言,视觉目标(单目标)…...

苏州狮山广场能耗管理系统
摘要:随着社会生活水平的提高,经济的繁荣发展,人们对能源的需求逐渐增长,由此带来的能源危机日益严重。商场如何实时的了解、分析和控制商场的能源消耗已成为需要解决的迫在眉睫的难题。传统的能源消耗智能以月/季度/年为周期进行…...

Jupyter Notebook 10个提升体验的高级技巧
Jupyter 笔记本是数据科学家和分析师用于交互式计算、数据可视化和协作的工具。Jupyter 笔记本的基本功能大家都已经很熟悉了,但还有一些鲜为人知的技巧可以大大提高生产力和效率。在这篇文章中,我将介绍10个可以提升体验的高级技巧。 改变注释的颜色 颜…...
CF 751 --B. Divine Array
Black is gifted with a Divine array a consisting of n (1≤n≤2000) integers. Each position in a has an initial value. After shouting a curse over the array, it becomes angry and starts an unstoppable transformation. The transformation consists of infinite…...

Springcloud1--->Eureka注册中心
目录 Eureka原理Eureka入门案例编写EurekaServer将user-service注册到Eureka消费者从Eureka获取服务 Eureka详解基础架构高可用的Eureka Server失效剔除和自我保护 Eureka原理 Eureka:就是服务注册中心(可以是一个集群),对外暴露自…...

面试阿里、字节全都一面挂,被面试官说我的水平还不如应届生
测试员可以先在大厂镀金,以后去中小厂毫无压力,基本不会被卡,事实果真如此吗?但是在我身上却是给了我很大一巴掌... 所谓大厂镀金只是不卡简历而已,如果面试答得稀烂,人家根本不会要你。况且要不是大厂出来…...

JAVA开发(记一次删除完全相同pgSQL数据库记录只保留一条)
进行数据管理时,无效数据可能会对生产力和决策质量造成严重的影响。如何发现和处理无效数据变得愈发重要。一起来唠唠你会如何处理无效数据吧~ 方向一:介绍无效数据的概念 最近遇到了pg数据库表中的大量数据重复了,需要删除其中的一条。一条…...

音视频八股文(7)-- 音频aac adts三层结构
AAC介绍 AAC(Advanced Audio Coding)是一种现代的音频编码技术,用于数字音频的传输和存储领域。AAC是MPEG-2和MPEG-4标准中的一部分,可提供更高质量的音频数据,并且相比于MP3等旧有音频格式,AAC需要更少的…...

Docker代码环境打包进阶 - DockerHub分享镜像
1. Docker Hub介绍 Docker Hub是一个广泛使用的容器镜像注册中心,为开发人员提供了方便的平台来存储、共享和分发Docker容器镜像。它支持版本控制、访问控制和自动化构建,并提供了丰富的公共镜像库,方便开发人员快速获取和使用各种开源应用和…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
React核心概念:State是什么?如何用useState管理组件自己的数据?
系列回顾: 在上一篇《React入门第一步》中,我们已经成功创建并运行了第一个React项目。我们学会了用Vite初始化项目,并修改了App.jsx组件,让页面显示出我们想要的文字。但是,那个页面是“死”的,它只是静态…...
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章 摘要: 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言,受限于 C 语言本身的内存安全和并发安全问题,开发复杂模块极易引入难以…...