Spring Security入门:认证授权与过滤器链实战解析
如果你打开过Spring Boot项目的启动日志大概率见过这样一行Using generated security password: 一串随机字符。第一次见的时候很多人以为是某个中间件随手打的日志直到访问任意接口被重定向到登录页才意识到——Spring Security已经被悄悄塞进项目里了。这种体验几乎成了 Java Web 开发者的共同记忆。Spring Security 作为 Spring 生态里的安全基础设施覆盖了登录认证、用户权限、接口保护、密码加密这些绕不开的问题。这篇是系列的入门篇我会把基础概念和快速入门两件事讲透先搞清楚它到底解决了什么问题、内部骨架长什么样再亲手跑通一个最小可用的登录应用。适合第一次接触 Spring Security、或者已经配置成功但说不清原理的人。1. 为什么Java Web项目绕不开Spring Security1.1 没有框架的年代认证代码是怎么写的聊 Spring Security 之前先回忆一下没有安全框架的日子。早期做 Servlet 项目登录检查基本靠约定。每个需要登录的接口入口处先取 Session判断里面有没有当前用户对象没有就response.sendRedirect(/login)。接口一多这段逻辑就会被复制到几十个地方。更麻烦的是权限升级比如某天产品说这个页面普通用户也能看了你得去翻代码找到对应的判断逻辑逐个改if条件。除了重复代码还有一堆容易踩的细节。Session 超时后要区分未登录和登录过期密码存数据库时直接明文或者用不带盐的 MD5 糊弄CSRF 防御没人管后端接口裸奔。这些问题不是不能自己解决但每做一个项目就要重写一遍写出来的方案还未必经过安全验证。我自己经历过一个真实场景某内部系统把所有接口都放在一个拦截器里做权限判断结果新来的同事不知道这个约定新加的几个接口没有放进拦截路径上线后数据泄露。这种靠自觉的安全策略迟早出事。1.2 Spring Security把安全问题拆成了两件大事Spring Security 的核心其实就是把安全这件事拆成了两个问题认证Authentication和授权Authorization。认证解决的是你是谁。你提交用户名密码系统校验凭证确认身份成立然后在后续请求中持续识别你。授权解决的是你能干什么。身份确认之后系统根据你的角色或权限决定哪些接口能访问、哪些操作能执行。举个门禁卡的例子刷卡识别身份是认证确认这张卡能开哪些门是授权。两者先先后后缺一不可。拆开之后Spring Security 把大量的公共细节都扛了下来Session 管理、登录页生成、密码加密、请求重定向、异常捕获、CSRF 防护甚至连密码错误还是用户不存在这种信息是否暴露给前端都替你想好了。开发者只需要关心业务层面的用户从哪里来、权限怎么定义剩下的交给框架。1.3 为什么Java社区最终收敛到它Java 生态里安全框架不止一个但 Spring Security 几乎是事实标准。原因也挺简单它和 Spring Boot 的自动装配配合得太好了加一个依赖就能获得一套完整的默认安全策略学习曲线可以很平缓需要定制的时候又通过过滤器链和一系列扩展点提供了足够深的弹性。我自己用下来的感受是Spring Security 的抽象很正。它没有堆砌一堆炫技的 API而是把认证、授权、会话、异常这些概念老老实实地建模。你花一个下午看懂它的过滤器链后面所有配置看起来都是顺理成章的。1.4 这个系列打算怎么讲这篇是系列的第一篇定位在概念 最小可用。我会先带你建立骨架级认知再跑通一个带登录页的 Spring Boot 应用。后续系列会逐步深入数据库用户存储、自定义登录页、方法级安全、OAuth2 接入、微服务场景下的安全方案。下一篇预告会在结尾给出现在先专注把地基打牢。2. 骨架级认知请求在过滤器链里经历了什么2.1 加一行依赖后启动日志里的随机密码是哪来的新建一个 Spring Boot 项目往pom.xml里加一行dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency启动项目控制台会打印一个随机密码。这个密码是框架自动生成的用于内置的默认用户user。不做任何配置的情况下Spring Boot 已经帮你完成了三件事所有接口默认需要认证、提供一个默认的表单登录页、支持基于 Session 的登录态保持。这背后是 Spring Boot 的自动装配在起作用。它注册了一条默认的SecurityFilterChain把安全策略接进了 Servlet 的过滤器链路。你要做的是在这条默认链上做定制而不是从零搭一套。2.2 过滤器链是一条安检流水线Servlet 规范里Filter可以在请求到达 Controller 之前和响应返回客户端之前插入逻辑。多个过滤器按顺序组成一条链。你可以把它想象成机场安检通道你的请求是乘客进入候机区前要依次经过行李扫描、身份核验、登机牌查验任何一环不过都会被拦下来。Spring Security 就是在这条链上塞了一组过滤器。入门阶段你需要认识几个关键角色SecurityContextHolderFilter负责在请求开始时从 Session 恢复登录身份请求结束时保存回去UsernamePasswordAuthenticationFilter处理表单登录请求解析用户名密码并执行认证AnonymousAuthenticationFilter没有登录的请求会被赋予一个匿名身份方便后续统一处理ExceptionTranslationFilter捕获认证和授权阶段的异常决定是重定向到登录页还是返回 403AuthorizationFilter做最终的授权判断确认当前身份是否有权限访问目标接口这些过滤器的先后顺序是有讲究的。身份恢复必须最早做因为后面的过滤器都要用到当前用户信息授权判断必须最晚做因为要先确认身份再谈权限。2.3 Authentication里到底装了什么认证过程中最核心的对象是Authentication。它像一个装了三个格子的盒子字段含义例子principal身份主体登录用户对象credentials凭证信息密码认证前有值认证后一般清空authorities权限列表ROLE_ADMIN、ROLE_USER以用户名密码登录为例。UsernamePasswordAuthenticationFilter拿到请求里的用户名和密码后会构造一个UsernamePasswordAuthenticationToken对象。注意这个名字里的Token不是那种 JWT Token它只是Authentication的一个实现表示这是一个待认证的身份。这个对象带着用户输入的凭证进入AuthenticationManager。AuthenticationManager会找合适的AuthenticationProvider来实际执行校验比如DaoAuthenticationProvider负责去UserDetailsService里加载用户再用PasswordEncoder比对密码。比对通过后原来那个未认证的Authentication对象会被替换成一个已认证的、包含完整权限信息的对象。2.4 SecurityContext和ThreadLocal的秘密认证通过后身份信息要存到一个地方供后续流程使用。Spring Security 的做法是先把已认证的Authentication放进SecurityContext再把SecurityContext放进SecurityContextHolder。SecurityContextHolder默认使用ThreadLocal存储。ThreadLocal可以理解为每个线程专属的储物柜同一个线程里任何代码都能从里面拿到当前用户信息但别的线程拿不到。这带来了一个隐患如果你在业务代码里新开了线程或者用了异步调用子线程默认是拿不到父线程里那份SecurityContext的。Spring Security 6.x 时代SecurityContextHolderFilter承担了核心的读写职责请求开始时从SecurityContextRepository默认基于 HttpSession 实现读取身份信息放进ThreadLocal请求结束时再写回仓库并清理ThreadLocal避免线程池复用导致信息串台。2.5 授权过滤器怎么用权限做判断身份有了权限也有了最后一关是AuthorizationFilter。它会根据你配置的安全规则比对请求路径和当前身份的authorities。这里有一个入门阶段很容易混淆的细节hasRole(ADMIN)实际上查询的是ROLE_ADMIN这个权限因为 Spring Security 约定角色必须以ROLE_开头。而hasAuthority(ADMIN)查询的就是单纯的ADMIN权限不加前缀。这个差异看起来不起眼实际踩坑的人不少后面我会专门讲。3. 快速跑通一个自带登录页的最小应用3.1 五分钟环境准备开始实操前确认你的环境JDK 17 及以上Spring Boot 3.x 的要求Maven 3.6 或 Gradle一个你顺手的 IDE用 Spring Initializr 创建一个 Spring Boot 项目依赖里勾选Spring Web和Spring Security。如果你更习惯手动写配置pom.xml里加这两段即可dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency版本直接继承父工程的spring-boot-starter-parent就行。我建议不要手动指定 Spring Security 的版本号避免和 Spring Boot 版本不匹配。3.2 第一次启动看默认行为什么都不配置直接启动应用。你会在控制台看到类似这样的输出Using generated security password: a1b2c3d4-e5f6-7890-...这时访问http://localhost:8080/浏览器会 302 重定向到http://localhost:8080/login一个简洁的登录页出现了。用户名是user密码就是上面那串随机字符串。输入正确后页面跳回原来的目标地址。这就是默认安全策略的全部表现所有路径需要认证、表单登录、基于 Session 的会话保持。你可以先亲手走一遍这个流程感受一下什么都不写就有了安全是什么体验。3.3 自定义安全配置和内存用户默认行为只能用来体验实际项目里肯定要自定义。最基础的定制是定义一个SecurityFilterChain配置类并指定用户存储。我创建一个SecurityConfig类package com.example.demo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; Configuration EnableWebSecurity public class SecurityConfig { Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth - auth .requestMatchers(/, /home, /css/**, /js/**, /images/**).permitAll() .anyRequest().authenticated() ) .formLogin(form - form .loginPage(/login) .defaultSuccessUrl(/index, true) .permitAll() ) .logout(logout - logout .logoutUrl(/logout) .logoutSuccessUrl(/login?logout) .permitAll() ); return http.build(); } Bean public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) { UserDetails admin User.builder() .username(admin) .password(passwordEncoder.encode(123456)) .roles(ADMIN) .build(); return new InMemoryUserDetailsManager(admin); } Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }这段配置做了几件事放行首页和静态资源其余接口必须认证开启表单登录登录成功后默认跳到/index定义了一个内存用户admin密码是 BCrypt 加密后的。再写一个简单的测试 Controllerpackage com.example.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; RestController public class HelloController { GetMapping(/) public String home() { return 欢迎来到首页; } GetMapping(/index) public String index() { return 登录成功后的页面; } GetMapping(/admin) public String admin() { return 只有管理员能看到的页面; } }这里的/admin暂时没有做角色限制访问它只需要登录即可。后面讲到授权时会补上。注意入门阶段为了演示方便可以先不关闭 CSRF。但如果你用 POST 接口测试登录后的操作会碰到 403这是 Spring Security 默认开启 CSRF 防护的结果。开发期可以在http配置链上加一句.csrf(AbstractHttpConfigurer::disable)生产环境一定要保留。具体原因在第五章详细讲。3.4 完整跑一遍登录流程配置完成后重新启动项目用admin/123456走一遍完整流程访问/hello未登录状态下被重定向到/login在登录页输入用户名密码提交UsernamePasswordAuthenticationFilter拦截/loginPOST 请求执行认证认证成功框架把认证信息写入 Session并重定向到之前想访问的地址本例中配置了固定跳转/index浏览器带着 Session Cookie 再次访问/helloSecurityContextHolderFilter从 Session 恢复身份请求正常放行这一步建议配合调试器或 Debug 日志看一遍过滤器的执行顺序比背十遍概念都管用。你在 IDE 里给UsernamePasswordAuthenticationFilter的doFilter方法打上断点然后提交一次登录就能清楚看到框架内部如何一步步处理你的凭证。3.5 先别急着扩展理解一下这段配置很多教程到这里就直接讲 OAuth2、JWT 了但我觉得入门阶段最该做的是理解那段SecurityFilterChain的 Lambda 写法。它本质上是对过滤器链的组装说明authorizeHttpRequests配置授权规则formLogin配置登录流程logout配置退出流程。每个方法对应的都是一组过滤器你在链上看到的每一个动作背后都有对应的实现类。看懂了这个对应关系后面学习自定义登录页、调整会话策略、接入 OAuth2 都会轻松很多。它们是同一个骨架上的不同零件而不是孤立的知识点。4. 密码不能裸奔PasswordEncoder与UserDetails的关键细节4.1 为什么数据库存密码要格外小心很多刚接触安全框架的人会觉得密码加密是个锦上添花的选项——反正系统内网访问泄露概率低。我见过不止一个项目把用户密码明文存进数据库或者只做一次不加盐的 MD5。这类做法一旦发生数据泄露风险是连锁性的用户在其他平台可能用了同一套密码攻击者拿着数据库就能横向撞库。加密密码的核心目的是让数据库泄露时攻击者也无法轻易还原原始密码。这里要注意加盐哈希和普通 Hash 是两回事。MD5 的问题是计算速度太快攻击者可以每秒尝试海量组合还可以用彩虹表直接查明文。而 BCrypt 这类算法故意设计得慢并且每次加密自动带上随机盐同样的密码每次生成的密文都不一样彩虹表基本失效。4.2 BCryptPasswordEncoder用起来其实很简单Spring Security 里最省心的PasswordEncoder实现是BCryptPasswordEncoder。用法很简单PasswordEncoder encoder new BCryptPasswordEncoder(); String encoded encoder.encode(123456); System.out.println(encoded); // $2a$10$7eq...每次运行结果都不同 boolean matched encoder.matches(123456, encoded); // true生成出来的字符串以$2a$10$开头其中10是 cost 参数代表计算强度。默认值是 10这个值越大计算越慢安全性越高但也越消耗 CPU。普通应用用默认值足够了硬件好、用户量大的场景可以调到 12不建议超过 14否则登录会明显卡顿。顺便说一个容易困惑的点User.builder().password(passwordEncoder.encode(123456))生成的是不带前缀的 BCrypt 密文。但在一些示例代码里你会看到密码字符串前面有{noop}这样的前缀。那是DelegatingPasswordEncoder在起作用它根据前缀委托给对应的编码器。{noop}表示明文不加密只用于演示或测试生产环境千万别用。4.3 UserDetails和InMemoryUserDetailsManager的真相内存用户存储用的InMemoryUserDetailsManager实现的是UserDetailsService接口——这个接口只有一个方法loadUserByUsername(String username)。框架在认证时会调用它按用户名查找用户拿回一个UserDetails对象。UserDetails接口里包含的字段比你想的多用户名、密码、权限列表以及四个返回boolean的方法——账号是否未过期、凭证是否未过期、账号是否未锁定、是否可用。这给了框架完整的能力去表达账号冻结密码过期需重置这类状态。实际项目中很少用InMemoryUserDetailsManager但理解它的位置很重要。将来你做数据库版用户存储本质上就是自己实现一个UserDetailsService从数据库查用户后组装成UserDetails返回。这个扩展点在系列下一篇会专门讲。4.4 涉及密码的几个新手雷区关于密码有几个我在答疑时反复遇到的情况先列出来让你有心理准备不要为了省事用{noop}它只是让人能直接用明文密码启动项目但会把不设防带入生产环境。改编码器后旧密码全失效如果你的系统以前用 MD5 存密码换了BCryptPasswordEncoder后新代码用 BCrypt 匹配旧密码永远匹配不上。平滑的做法是用DelegatingPasswordEncoder配置多种编码器新密码用 BCrypt 编码带前缀标识旧密码用旧算法校验用户下次登录成功后再升级存储格式。数据库字段长度要留够BCrypt 密文长度固定是 60 个字符但有些字段设计成 32 位或 45 位放不下保存时会报错。要么预留 68 位要么用varchar(255)。User.builder()里不要直接放明文password方法接收的是待存储的密文框架不会帮你加密。你放明文框架就存明文。密码这块虽然基础但直接影响整个系统的安全底线值得花时间一次搞明白。5. 快速入门必踩的几个坑和一套清晰的排查思路5.1 请求总是跳回登录页先按这条链路查我明明登录成功了为什么访问某个接口又跳到登录页——这是入门阶段最经典的问题。我的排查习惯是按下述顺序来查配置是否生效确认你写的SecurityConfig被 Spring 扫描到了。类上必须有Configuration并确保它在启动类的扫描路径下。查请求路径是否匹配requestMatchers写的路径和实际访问路径是否一致。比如放行了/user/**但接口实际路径是/userInfo那就不匹配。查是否落到anyRequest().authenticated()如果请求匹配了更具体的规则后面更宽松的规则不会覆盖它但反过来没匹配到任何规则就落到兜底规则被要求认证。查会话是否正常登录成功后浏览器是否保存了 Session Cookie如果你用curl手动测试不会自动携带 Cookie每次请求自然都是未登录。排查时把 Spring Security 的日志调到 DEBUG 会事半功倍logging: level: org.springframework.security: DEBUG日志里会明确告诉你请求匹配了哪条规则、当前用户是否匿名、被哪个过滤器拦截。5.2 hasRole、hasAuthority、roles到底怎么收尾权限相关的方法名看着都差不多实际规则很严格。还是那张表讲清楚配置写法底层查询的权限匹配的权限来源hasRole(ADMIN)ROLE_ADMIN用户拥有ROLE_ADMINhasAuthority(ROLE_ADMIN)ROLE_ADMIN用户拥有ROLE_ADMINhasAuthority(ADMIN)ADMIN用户拥有ADMIN不带前缀入口处用roles(ADMIN)构造用户实际添加的权限是ROLE_ADMIN用authorities(ADMIN)构造添加的权限是ADMIN。如果你入口用了authorities(ADMIN)接口规则却写hasRole(ADMIN)结果就是 403。这类写成两边前缀不一致是权限拦截最常见的低级错误。5.3 一个典型的403CSRF默认开启刚接触 Spring Security 时很多人会遇到一个诡异现象登录页能正常打开登录也能成功但只要一提交 POST 请求就 403。这大概率是 CSRF 防护在起作用。CSRF 攻击的原理是攻击者诱导已登录用户在不知情的情况下向你的系统发送伪造请求。Spring Security 默认要求所有会改变状态的请求POST、PUT、DELETE都携带一个随机 Token 才算合法。对于同样是表单 POST 的登录请求框架已经帮你把 Token 写进了登录页表单但对于你自己写的普通 POST 接口如果你没有在页面上获取并提交这个 Token请求就会被拒。入门阶段如果只是在本地捣鼓可以先关掉 CSRFF 方便调试http.csrf(AbstractHttpConfigurer::disable);但你要清醒生产环境必须保留而且要在页面或者 AJAX 请求里正确携带 Token。具体怎么做系列后面我会单独写一篇讲。5.4 异常信息怎么读Spring Security 的异常类不算少入门阶段认识最常见的几个就够了异常表现排查方向BadCredentialsException登录页提示用户名或密码错误表单用户名/密码是否正确密码是否用同一个PasswordEncoder校验AccessDeniedException已登录但权限不足返回 403检查接口规则和用户拥有的权限是否匹配DisabledException/LockedException用户被禁用/锁定检查UserDetails里对应布尔方法的状态未登录访问受保护接口重定向到登录页检查会话是否失效、请求是否携带 Cookie读异常信息时把握一个核心判断跳到登录页说明还没认证直接 403 说明认证成功但权限不足。这两者界定的方式在 ExceptionTranslationFilter 里它会把访问受保护资源时的异常分类处理——未认证就去走认证流程已认证就返回 403。6. 给入门阶段的读者几句实在话这篇的内容量不小但核心其实就三个过滤器链是骨架、Authentication 是血液、配置类是组装说明。你不需要把每个过滤器都背下来但至少要能在脑里画出请求从浏览器到 Controller 之间经过了哪几道关键检查。我对入门者的建议是先照本文的配置把项目跑通然后把配置里的permitAll、authenticated、formLogin逐个改成不同组合观察访问控制的变化。这个改一下、跑一次、看结果的过程比看十篇教程都有效。自己动手把登录流程走顺之后再回头看书里的概念会突然发现那些名词都活了。下一篇会讲数据库用户存储如何从数据库查询用户、实现自己的UserDetailsService、自定义登录页和登录成功后的处理逻辑顺便把登录认证的完整时序再过一遍。如果你照着本文把最小应用跑通了下一篇的内容会衔接得很自然。我在这系列里踩过的坑都会尽量提前帮你标记出来。

相关新闻

AI快速进步但不会通用超级智能:技术约束与工程实践判断

AI快速进步但不会通用超级智能:技术约束与工程实践判断

1. 为什么这个判断值得认真对待1.1 一个反直觉但越来越主流的观点AI 会快速进步,但不会走向通用超级智能——这个判断乍一听有点矛盾。既然进步快,为什么不会走到那一步?但如果你真的在一线做模型训练、做产品落地、做推理优化,你…

2026/10/12 3:30:04 阅读更多 →
一小时搞懂扩散模型:从DDPM原理到Stable Diffusion实战

一小时搞懂扩散模型:从DDPM原理到Stable Diffusion实战

1. 为什么扩散模型值得你花一小时搞懂如果你最近在关注图像生成领域,大概率已经被"扩散模型"这四个字反复刷屏。不管是文生图、图生图、超分辨率重建,还是视频生成、音频合成,背后几乎都站着同一个核心架构——Diffusion Model。但…

2026/10/12 3:30:04 阅读更多 →
OpenAI Realtime 语音 API 的 Python 客户端:ell 仓库 openai_realtime 子项目实战解析

OpenAI Realtime 语音 API 的 Python 客户端:ell 仓库 openai_realtime 子项目实战解析

人工智能大模型提示工程AI 应用 【免费下载链接】ell A language model programming library. 项目地址: https://gitcode.com/gh_mirrors/ell/ell 点击查看 免费下载 x/openai_realtime 是 ell 语言模型编程仓库中的一个独立子项目:它把 OpenAI 官方的…

2026/10/12 3:29:03 阅读更多 →

最新新闻

PostgreSQL性能压测实战:用TPC-H标准流程构建可复现基准测试环境

PostgreSQL性能压测实战:用TPC-H标准流程构建可复现基准测试环境

1. 项目概述:为什么TPC-H是检验PostgreSQL真实能力的“压力测试仪”你刚装好PostgreSQL,跑通了第一个CREATE TABLE,连上pgAdmin点了几次查询,心里有点小得意——数据库这玩意儿,好像也没那么难?别急&#x…

2026/10/12 5:09:00 阅读更多 →
基于Spring Boot的车牌识别停车场管理系统设计与实现

基于Spring Boot的车牌识别停车场管理系统设计与实现

1. 项目概述与选题价值1.1 这个系统到底解决什么问题我第一次看到这个题目的时候,第一反应是:这又是一个“典型的毕业设计式管理系统”?因为现在网上关于停车场、图书馆、宿舍管理这类CRUD项目太多了,很多同学开题时随手挑一个&am…

2026/10/12 5:09:00 阅读更多 →
Spring Boot农事管理系统毕业设计:从数据库建模到核心功能实现

Spring Boot农事管理系统毕业设计:从数据库建模到核心功能实现

写这个题目前,我先说句实在话:Spring Boot 农事管理系统,这个搭配在国内农业信息化方向的毕业设计里,已经算得上“经典款”了。经典意味着什么?意味着参考资料好找、技术路线成熟、踩坑记录也很多,不至于让…

2026/10/12 5:09:00 阅读更多 →
MATLAB快速谱相干:从一维时间序列到旋转机械多通道分析

MATLAB快速谱相干:从一维时间序列到旋转机械多通道分析

前几天我在一个设备诊断交流群里看到有人贴图:同一条轴上的两路振动信号,普通幅值谱看着都差不多,在某个轴承故障特征频率附近却同时出现了一处明显的相干峰。下面跟了几条回复,有人问“相干峰到底代表什么”,有人说“…

2026/10/12 5:09:00 阅读更多 →
SpringBoot+Vue+MySQL旅游网站毕设项目全解析:从数据库设计到部署答辩

SpringBoot+Vue+MySQL旅游网站毕设项目全解析:从数据库设计到部署答辩

每年毕业季我都会收到大量和“旅游网站”相关的咨询,这套 SpringBootVueMySQL 的某北方城市特色旅游网站平台,属于完成度很高的一类毕设项目。它带了完整数据库脚本、论文文档和部署说明,代码结构比多数网上流传的“半成品”要规矩得多。这篇…

2026/10/12 5:09:00 阅读更多 →
微客AI助手答疑:AI客服的会话记录存在哪?留存位置与合规要点

微客AI助手答疑:AI客服的会话记录存在哪?留存位置与合规要点

给商家配微客AI助手的时候,被问过的最认真的一组问题来自一位做母婴用品的店主。她问的不是价格也不是功能,而是:客户的聊天记录存在哪?谁能看到?会不会被拿去做别的?说实话,这三个问题比大多数…

2026/10/12 5:08:00 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练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/11 14:36:54 阅读更多 →