从认证到数据权限:SpringBoot3 + Sa-Token + AOP实现企业级安全体系
一、问题背景做企业级应用开发这些年我见过太多项目把安全简化成加个登录就行。登录验证只是安全体系的第一道门真正的企业级安全是一个多层防护体系。之前在给政府客户交付项目时安全评审环节就遇到过一个尴尬系统有登录但同一个部门的用户能互相看到对方的数据审计日志里找不到任何操作记录XSS漏洞扫描扫出一堆的中危问题。为什么需要多层安全防护因为攻击者不会只盯着登录接口。一个完整的企业级安全体系至少需要覆盖这几个场景密码在传输过程中被截获怎么办——传输加密登录凭证过期了怎么处理——认证鉴权用户登录后能访问哪些功能——接口权限用户能看到哪些数据——数据权限恶意请求如何防御——安全防护层YSCode忆笙智云的安全体系设计从立项之初就考虑了多层防护。二、安全体系全景整个安全体系分为四层每层之间相互独立又依次递进层级模块技术实现说明第一层传输加密前端SM4国密算法加密防止中间人抓包获取明文密码第二层认证鉴权Sa-Token 1.43.0 JWT Simple模式 Redis登录验证、Token生成、会话管理第三层权限控制RBAC(用户-角色-菜单) 数据权限AOP功能权限 数据范围双重控制第四层安全防护CSRF/ XSS/ 演示模式/ IP黑白名单防御常见Web攻击和越权操作这四层构成了一个纵深防御体系。单点失效不会导致整体安全崩溃每一层都提供了独立的安全保障。三、传输加密层为什么用SM4登录接口的密码传输是安全的第一道防线。即使上了HTTPS某些内网环境下比如公司网络出口有SSL解密设备抓包工具仍然可能截获请求体。SM4是国密对称加密算法在前端对密码字段加密后再传输即使请求被截获也无法还原明文密码。选择SM4而不是AES的原因政府项目、金融项目、国企项目中国密算法是硬性要求。SM4在安全性和合规性上都满足要求。前端加密逻辑简化// login.vue - 登录时密码加密 import { sm4 } from /utils/encrypt; const login async () { // 1. SM4加密密码 const encryptedPassword sm4.encrypt(loginForm.password); // 2. 发送加密后的登录请求 const res await loginApi({ username: loginForm.username, password: encryptedPassword, uuid: captchaKey, // 验证码唯一标识 code: loginForm.code, // 验证码 }); // 3. 存储Token备用 localStorage.setItem(token, res.data.token); // 4. 跳转到首页 router.push(/); };SM4加密工具类实现前端 TypeScript// utils/encrypt.ts import { SM4 } from gm-crypto; const SM4_KEY your-16-byte-key!; // 16字节密钥与后端保持一致 export const sm4 { encrypt(plainText: string): string { return SM4.encrypt(plainText, SM4_KEY, { inputEncoding: utf8, outputEncoding: base64, }); }, decrypt(cipherText: string): string { return SM4.decrypt(cipherText, SM4_KEY, { inputEncoding: base64, outputEncoding: utf8, }); }, };四、认证流程从密码验证到Token生成用户登录的完整链路前端Vue → SM4加密密码 → POST /login 后端 → SM4解密 → BCrypt密码比对 → Sa-Token生成JWT → Redis存储会话 返回 → JWT Token → 前端localStorage存储 → 后续请求Header携带后端解密和验证PostMapping(/login) public RLoginResult login(RequestBody LoginBody body) { // 1. SM4解密密码 String rawPassword Sm4Util.decrypt(body.getPassword()); // 2. BCrypt密码验证 SysUser user userService.getByUsername(body.getUsername()); if (user null) { throw new BusinessException(用户不存在); } if (!BCrypt.checkpw(rawPassword, user.getPassword())) { throw new BusinessException(用户名或密码错误); } // 3. 检查用户状态 if (0.equals(user.getStatus())) { throw new BusinessException(账号已被停用); } // 4. Sa-Token生成JWT并存入Redis StpUtil.login(user.getId()); String token StpUtil.getTokenValue(); // 5. 记录登录信息 user.setLoginIp(ServletUtils.getClientIP()); user.setLoginDate(new Date()); userService.updateById(user); // 6. 返回Token和用户信息 return R.ok(LoginResult.builder() .token(token) .userInfo(convert(user)) .build()); }关键点说明BCrypt是单向哈希每次加密的盐值不同即使相同密码每次生成的密文也不同。这意味着即使数据库泄露攻击者也无法通过彩虹表还原密码Sa-Token JWT Simple模式将Token作为JWT payload同时保持Session存储在Redis中。纯JWT方案无法主动踢人下线而Sa-Token的混合模式兼顾了JWT的无状态优势和服务端会话管理的灵活性Redis存储会话信息支持分布式部署下多节点共享登录状态服务重启不会丢失会话Sa-Token配置application.ymlsa-token: token-name: Authorization timeout: 2592000 # Token有效期30天 active-timeout: 1800 # 30分钟无操作自动下线 is-concurrent: false # 不允许同一账号并发登录 is-share: false # 多端不共享会话 token-style: simple # Simple风格Token is-log: true # 开启日志 jwt-secret-key: ${JWT_SECRET} # JWT密钥从环境变量读取五、权限体系RBAC 注解式权限控制权限模型采用标准的RBAC用户 → 角色 → 菜单SysUser用户 ──多对多──▶ SysRole角色 ──多对多──▶ SysMenu菜单/按钮菜单权限分为三个粒度从粗到细权限类型控制范围示例实现方式菜单权限控制左侧菜单可见性用户管理菜单是否显示后端返回菜单树时过滤按钮权限控制页面内按钮显示新增、编辑、删除按钮前端 v-auth 指令接口权限控制后端API访问控制器方法级别的权限校验SaCheckPermission 注解后端接口权限控制示例RestController RequestMapping(/system/user) public class SysUserController { // 查看用户列表 - 需要 system:user:list 权限 SaCheckPermission(system:user:list) GetMapping(/list) public RTableDataInfo list(SysUser user, PageQuery pageQuery) { return R.ok(userService.selectPageUserList(user, pageQuery)); } // 查看用户详情 - 需要 system:user:query 权限 SaCheckPermission(system:user:query) GetMapping(/{userId}) public RSysUser getInfo(PathVariable Long userId) { return R.ok(userService.selectUserById(userId)); } // 新增用户 - 需要 system:user:add 权限 SaCheckPermission(system:user:add) PostMapping public RVoid add(Validated RequestBody SysUser user) { // 密码加密 user.setPassword(BCrypt.hashpw(user.getPassword())); userService.insertUser(user); return R.ok(); } // 编辑用户 - 需要 system:user:edit 权限 SaCheckPermission(system:user:edit) PutMapping public RVoid edit(Validated RequestBody SysUser user) { userService.updateUser(user); return R.ok(); } // 删除用户 - 需要 system:user:remove 权限 SaCheckPermission(system:user:remove) DeleteMapping(/{userIds}) public RVoid remove(PathVariable Long[] userIds) { userService.deleteUserByIds(userIds); return R.ok(); } // 导出用户 - 需要 system:user:export 权限 SaCheckPermission(system:user:export) PostMapping(/export) public void export(HttpServletResponse response, SysUser user) { ListSysUser list userService.selectUserList(user); ExcelUtil.exportExcel(response, list, 用户数据); } }Sa-Token的SaCheckPermission注解还支持角色校验和逻辑组合// 单一权限校验 SaCheckPermission(system:user:list) // 多权限OR组合满足任一即可 SaCheckPermission( value {system:user:add, system:user:edit}, mode SaMode.OR ) // 多权限AND组合必须全部满足 SaCheckPermission( value {system:user:list, system:user:add}, mode SaMode.AND ) // 角色校验 SaCheckRole(admin)六、数据权限AOP注解式拦截接口权限控制的是能不能访问这个功能数据权限控制的是能看到哪些数据。举个例子部门经理只能看到本部门的数据普通员工只能看到自己的数据总经理能看到全部数据。数据权限的实现基于AOP注解 SQL自动拼接无需在每个查询方法中手写过滤条件// 数据权限注解 Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) public interface DataScope { // 部门表别名 String deptAlias() default ; // 用户表别名 String userAlias() default ; // 权限字段名 String permissionField() default dataScope; }AOP切面逻辑核心部分Aspect Component public class DataScopeAspect { Before(annotation(dataScope)) public void doBefore(JoinPoint point, DataScope dataScope) { // 1. 获取当前登录用户 LoginUser loginUser SecurityUtils.getLoginUser(); SysUser currentUser loginUser.getUser(); // 2. 超级管理员跳过数据权限过滤 if (loginUser.isAdmin()) { return; } // 3. 构建数据权限过滤SQL StringBuilder sqlString new StringBuilder(); String roleIds loginUser.getRoleIds(); // 全部数据权限 - 不添加任何过滤 if (DataScopeType.ALL.getCode().equals(currentUser.getDataScope())) { return; } // 自定义数据权限 - 根据角色配置的部门范围过滤 else if (DataScopeType.CUSTOM.getCode().equals(currentUser.getDataScope())) { sqlString.append(String.format( OR %s.dept_id IN (SELECT dept_id FROM sys_role_dept WHERE role_id IN (%s)), dataScope.deptAlias(), roleIds)); } // 本部门数据权限 else if (DataScopeType.DEPT.getCode().equals(currentUser.getDataScope())) { sqlString.append(String.format( OR %s.dept_id %d, dataScope.deptAlias(), currentUser.getDeptId())); } // 本部门及以下数据权限 ... // 仅本人数据权限 ... // 4. 将SQL条件注入到分页参数中 // 去掉开头的 OR 用 AND (包裹 if (sqlString.length() 0) { String condition sqlString.substring(4); // 遍历方法参数找到PageQuery对象 ... } } }使用方式非常简洁在Service方法上添加一行注解即可// 在Service方法上添加注解 DataScope(deptAlias d, userAlias u) public ListSysUser selectUserList(SysUser user) { return userMapper.selectUserList(user); }对应的Mapper XML中通过${params.dataScope}动态拼接过滤条件select idselectUserList resultTypeSysUser SELECT u.user_id, u.username, u.nick_name, u.email, u.phone, u.status, u.create_time, d.dept_name FROM sys_user u LEFT JOIN sys_dept d ON u.dept_id d.dept_id WHERE u.del_flag 0 if testusername ! null and username ! AND u.username LIKE CONCAT(%, #{username}, %) /if if teststatus ! null and status ! AND u.status #{status} /if !-- 数据权限条件自动拼接 -- ${params.dataScope} ORDER BY u.create_time DESC /select数据权限的五种类型权限类型常量数据范围适用角色全部数据ALL查看所有数据超级管理员自定义数据CUSTOM按角色配置的部门范围分管领导本部门数据DEPT仅本部门数据部门经理本部及以下DEPT_AND_CHILD本部门和所有子部门部门负责人仅本人数据SELF仅自己创建的数据普通员工七、安全防护层CSRF Token校验CSRF跨站请求伪造攻击原理攻击者诱导用户点击恶意链接利用用户已登录的Session发起伪造请求。YS-LowCode通过CSRF Token机制防御public class CsrfInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // GET请求不校验CSRF if (GET.equalsIgnoreCase(request.getMethod())) { return true; } // 从请求头获取CSRF Token String csrfToken request.getHeader(X-CSRF-TOKEN); // 从Redis获取服务端CSRF Token String serverToken StpUtil.getSession() .getString(CSRF_TOKEN); if (StringUtils.isBlank(csrfToken) || !csrfToken.equals(serverToken)) { log.warn(CSRF Token校验失败: IP{}, URI{}, ServletUtils.getClientIP(), request.getRequestURI()); throw new BusinessException(CSRF Token校验失败请刷新页面后重试); } return true; } }XSS过滤器通过自定义的XssHttpServletRequestWrapper对请求参数进行过滤防止恶意脚本注入public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { Override public String[] getParameterValues(String name) { String[] values super.getParameterValues(name); if (values null) return null; return Arrays.stream(values) .map(this::clean) .toArray(String[]::new); } Override public String getParameter(String name) { return clean(super.getParameter(name)); } Override public String getHeader(String name) { return clean(super.getHeader(name)); } private String clean(String value) { if (StringUtils.isBlank(value)) return value; // 过滤script标签及其内容 value value.replaceAll((?i)script.*?.*?/script, ); // 过滤iframe标签 value value.replaceAll((?i)iframe.*?.*?/iframe, ); // 过滤on事件属性 value value.replaceAll((?i)on\\w\\s*, _disabled); // 过滤javascript:伪协议 value value.replaceAll((?i)javascript:, ); // 过滤expression表达式 value value.replaceAll((?i)expression\\s*\\(, ); // 过滤HTML标签 value value.replaceAll([^]*, ); return value; } }XSS过滤器注册Configuration public class FilterConfig { Bean public FilterRegistrationBeanXssFilter xssFilterRegistration() { FilterRegistrationBeanXssFilter registration new FilterRegistrationBean(); registration.setFilter(new XssFilter()); registration.addUrlPatterns(/*); registration.setName(xssFilter); registration.setOrder(1); // 排除不需要过滤的路径 registration.addInitParameter(excludes, /system/notice/*); return registration; } }演示模式拦截器开放演示环境时需要拦截所有写操作防止数据被恶意篡改Component public class DemoModeInterceptor implements HandlerInterceptor { Value(${demo.enabled:false}) private boolean demoEnabled; Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { if (!demoEnabled) return true; // 演示模式下非GET请求全部拦截 if (!GET.equalsIgnoreCase(request.getMethod())) { // 排除登录接口 String uri request.getRequestURI(); if (uri.contains(/login)) { return true; } throw new BusinessException(演示模式不允许执行写操作); } return true; } }IP黑白名单通过配置项精确控制访问来源支持单个IP和CIDR网段# application.yml security: ip-whitelist: enabled: true ips: 192.168.1.0/24,10.0.0.1,10.0.0.2 ip-blacklist: enabled: true ips: 58.218.204.100,185.220.101.0/24IP黑白名单实现Component public class IpFilter implements Filter { Value(${security.ip-whitelist.enabled:false}) private boolean whitelistEnabled; Value(${security.ip-whitelist.ips:}) private String whitelistIps; Value(${security.ip-blacklist.enabled:false}) private boolean blacklistEnabled; Value(${security.ip-blacklist.ips:}) private String blacklistIps; private ListSubnetUtils whitelistSubnets; private ListSubnetUtils blacklistSubnets; PostConstruct public void init() { whitelistSubnets parseSubnets(whitelistIps); blacklistSubnets parseSubnets(blacklistIps); } Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { String clientIp ServletUtils.getClientIP((HttpServletRequest) request); // 先检查黑名单 if (blacklistEnabled isInSubnets(clientIp, blacklistSubnets)) { log.warn(IP黑名单拦截: {}, clientIp); ((HttpServletResponse) response).sendError(403, IP已被禁止访问); return; } // 再检查白名单 if (whitelistEnabled !isInSubnets(clientIp, whitelistSubnets)) { log.warn(IP白名单拦截: {}, clientIp); ((HttpServletResponse) response).sendError(403, IP不在允许范围内); return; } chain.doFilter(request, response); } private boolean isInSubnets(String ip, ListSubnetUtils subnets) { if (subnets.isEmpty()) return false; return subnets.stream().anyMatch(subnet - { try { return subnet.getInfo().isInRange(ip); } catch (Exception e) { return false; } }); } }八、前端权限控制Auth组件前端通过Auth组件实现三种权限控制方式覆盖所有使用场景方式一v-auth指令最简洁template div classuser-management el-button v-authsystem:user:add typeprimary iconPlus新增/el-button el-button v-authsystem:user:import typesuccess iconUpload导入/el-button el-button v-authsystem:user:export typewarning iconDownload导出/el-button el-button v-authsystem:user:remove typedanger iconDelete删除/el-button /div /templatev-auth指令实现原理// directives/auth.ts import type { Directive, DirectiveBinding } from vue; import { useUserStore } from /store/user; export const auth: Directive { mounted(el: HTMLElement, binding: DirectiveBinding) { const { value } binding; const userStore useUserStore(); const permissions userStore.permissions; if (value value instanceof Array value.length 0) { const hasPermission value.some(v permissions.includes(v)); if (!hasPermission) { el.parentNode?.removeChild(el); } } else if (value) { const hasPermission permissions.includes(value); if (!hasPermission) { el.parentNode?.removeChild(el); } } else { throw new Error(v-auth 指令需要传入权限标识); } }, };方式二auth函数用于JS逻辑判断import { hasPermi, hasRole } from /utils/auth; // 判断是否有某个权限 if (hasPermi(system:user:edit)) { // 执行编辑操作 dialogVisible.value true; } // 判断是否有某个角色 if (hasRole(admin)) { // 管理员才能执行的操作 showAdminMenu.value true; } // 判断是否同时拥有多个权限 if (hasPermi([system:user:add, system:user:edit])) { // 同时拥有新增和编辑权限 }权限判断函数实现// utils/auth.ts import { useUserStore } from /store/user; export function hasPermi(permission: string | string[]): boolean { const userStore useUserStore(); const permissions userStore.permissions; if (Array.isArray(permission)) { // AND模式必须同时拥有所有权限 return permission.every(p permissions.includes(p)); } return permissions.includes(permission); } export function hasRole(role: string | string[]): boolean { const userStore useUserStore(); const roles userStore.roles; if (Array.isArray(role)) { return role.some(r roles.includes(r)); } return roles.includes(role); }方式三Auth组件包裹多个元素template Auth :valuesystem:user:export el-button typewarning批量导出/el-button el-divider directionvertical / el-button typeprimary批量审核/el-button /Auth /template这三种方式的设计逻辑v-auth指令适合单个元素的权限控制auth函数适合JS逻辑中的条件判断Auth组件适合需要包裹多个元素统一控制的场景。三者互补覆盖了前端所有权限控制需求。九、总结一个企业级安全体系不是简单的登录 权限注解而是从传输加密、认证鉴权、接口权限、数据权限、安全防护多个维度构建的纵深防御体系。YS-LowCode的安全方案覆盖了这五个维度SM4国密加密保证传输安全Sa-Token JWT Redis保证认证可靠RBAC AOP数据权限保证授权精细CSRF/XSS/IP黑白名单保证防护全面。这套方案在政府和企业项目中经过了多次安全评审的实际检验可以直接用于生产环境。

相关新闻

掌握libcurl:从GET请求到HTTPS验证全解析

掌握libcurl:从GET请求到HTTPS验证全解析

1. 初始化 libcurl 在程序开始时调用一次&#xff1a; #include <stdio.h> #include <curl/curl.h>int main(void) {CURLcode res;res curl_global_init(CURL_GLOBAL_DEFAULT);if (res ! CURLE_OK) {fprintf(stderr, "curl_global_init failed: %s\n",c…

2026/10/17 23:58:06 阅读更多 →
深入解析TI HDVPSS intc_intr1中断控制器:原理、配置与实战优化

深入解析TI HDVPSS intc_intr1中断控制器:原理、配置与实战优化

1. 项目概述在嵌入式视频处理系统的开发中&#xff0c;中断控制器就像是整个系统的“神经中枢”&#xff0c;它负责接收来自各个外设的“紧急呼叫”&#xff0c;并决定是否、以及何时通知CPU这个“大脑”去处理。今天&#xff0c;我们就来深入拆解德州仪器高清视频处理子系统中…

2026/10/17 20:51:07 阅读更多 →
中国电子多项AI创新成果入选国资央企人工智能典型案例

中国电子多项AI创新成果入选国资央企人工智能典型案例

2026世界人工智能大会&#xff08;WAIC&#xff09;期间&#xff0c;国务院国资委在“智赋新质 全域焕新”企业人工智能高质量发展论坛上正式启动“国资央企智能软件工厂联合筑基工程”&#xff0c;包括中国电子在内的首批13家中央企业研发力量参与共建。第二批央企人工智能战略…

2026/10/18 4:22:24 阅读更多 →

最新新闻

Java医药系统实战:权限分层、库存事务与财务统计闭环

Java医药系统实战:权限分层、库存事务与财务统计闭环

简介&#xff1a;本资源是一套基于Java Web与MySQL开发的医药销售管理课程设计系统&#xff0c;面向计算机专业本科生及Java初学者&#xff0c;解决中小型医药企业员工与经理在会员管理、供应商协作、药品库存查询、采购销售及仓库盘点等核心业务中的信息化需求。压缩包共26个文…

2026/10/18 13:01:44 阅读更多 →
krpano全景漫游制作全攻略:从静态照片到交互式虚拟展厅

krpano全景漫游制作全攻略:从静态照片到交互式虚拟展厅

简介&#xff1a;这是一份krpano 1.19-pr9全景图工具资源包&#xff0c;面向需要制作360全景展示的网页设计师、VR内容开发者和摄影爱好者。资源提供从原始照片自动拼接合成全景图&#xff0c;到生成可在PC与移动端流畅浏览的HTML5交互页面&#xff0c;以及将全景拆分为六张素材…

2026/10/18 13:01:44 阅读更多 →
用JavaScript实现PDF在线预览:从渲染内核到Canvas的完整指南

用JavaScript实现PDF在线预览:从渲染内核到Canvas的完整指南

简介&#xff1a;面向Web前端开发者的PDF在线预览实践资料&#xff0c;以PDF.js为核心&#xff0c;覆盖从库引入、文档加载、Canvas渲染到多页浏览、缩放控制、进度提示、文本选择等关键能力&#xff0c;并涉及Web Worker后台解析与性能优化思路&#xff0c;适合有一定JavaScri…

2026/10/18 13:01:43 阅读更多 →
Git核心模型与高频命令:版本控制从理解到实战

Git核心模型与高频命令:版本控制从理解到实战

1. 为什么每个开发者都要重新认识Git如果你写过代码&#xff0c;大概率有过这样的经历&#xff1a;项目改到第三版&#xff0c;想要找回昨天还能跑通的逻辑&#xff0c;结果发现文件被覆盖了&#xff1b;或者团队几个人同时改同一个文件&#xff0c;互相发压缩包&#xff0c;最…

2026/10/18 13:01:43 阅读更多 →
不懂 Lean 4 也能用 MathForm-8B?新手入门必备的完全指南

不懂 Lean 4 也能用 MathForm-8B?新手入门必备的完全指南

【免费下载链接】MathForm-8B 项目地址&#xff1a; https://ai.gitcode.com/OpenBMB/MathForm-8B 点击查看 免费下载 MathForm-8B 是一个开源的数学自动形式化模型&#xff1a;只要输入自然语言描述的数学问题&#xff0c;它就能帮你翻译成可被机器验证的 Lean 4 形式化定理。…

2026/10/18 13:01:43 阅读更多 →
安全审计必备:网络流量分析实战与异常发现指南

安全审计必备:网络流量分析实战与异常发现指南

1. 这一切&#xff0c;还得从一次“差点漏掉”的告警说起有次我蹲在机房排查一个深夜告警&#xff0c;日志里干干净净&#xff0c;主机层面没有任何异常进程&#xff0c;登录记录也没问题&#xff0c;但是外联流量在凌晨三点有一个非常规律的小尖峰&#xff0c;持续了大概五分钟…

2026/10/18 13:00:43 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →