备案里的网站名称威海做企业网站

张小明 2026/3/2 19:54:34
备案里的网站名称,威海做企业网站,网站被镜像怎么办,asp网站建设实录前言作为一名互联网软件开发人员#xff0c;你是否曾在项目中遇到过这样的困境#xff1a;Spring Security 默认的内存认证方式在实际生产环境中根本不够用#xff0c;想要接入自己的用户数据库却不知从何下手#xff1f;别担心#xff0c;今天这篇文章将带你一步步攻克这…前言作为一名互联网软件开发人员你是否曾在项目中遇到过这样的困境Spring Security 默认的内存认证方式在实际生产环境中根本不够用想要接入自己的用户数据库却不知从何下手别担心今天这篇文章将带你一步步攻克这个难题用最接地气的方式讲解如何在 Spring Boot3 中实现基于自定义数据库的安全鉴权体系。为什么需要自定义数据库鉴权在开发初期很多人会图方便直接使用 Spring Security 提供的InMemoryUserDetailsManager通过硬编码的方式存储用户名和密码。但这种方式存在三个致命问题首先是数据持久性问题应用重启后所有用户信息都会丢失这在生产环境中是绝对不能接受的。其次是扩展性局限当用户数量超过 10 个时硬编码方式会让代码变得臃肿不堪。最后是权限管理缺失真实业务中往往需要基于角色的细粒度权限控制内存模式很难满足这种需求。根据 Stack Overflow 2024 年的开发者调查显示83% 的企业级应用都会选择数据库存储用户信息其中 MySQL 以 67% 的占比成为最受欢迎的选择。这也是我们今天选择 MySQL 作为示例数据库的原因。前期准备搭建基础环境2.1 数据库设计首先我们需要设计用户表和角色表这里采用最经典的多对多关系模型-- 用户表 CREATE TABLE sys_user ( id bigint NOT NULL AUTO_INCREMENT COMMENT 用户ID, username varchar(50) NOT NULL COMMENT 用户名, password varchar(100) NOT NULL COMMENT 加密后的密码, enabled tinyint NOT NULL DEFAULT 1 COMMENT 是否启用(1启用,0禁用), create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username) COMMENT 用户名唯一 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统用户表; -- 角色表 CREATE TABLE sys_role ( id bigint NOT NULL AUTO_INCREMENT COMMENT 角色ID, role_name varchar(50) NOT NULL COMMENT 角色名称, role_code varchar(50) NOT NULL COMMENT 角色编码, PRIMARY KEY (id), UNIQUE KEY uk_role_code (role_code) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统角色表; -- 用户角色关联表 CREATE TABLE sys_user_role ( user_id bigint NOT NULL COMMENT 用户ID, role_id bigint NOT NULL COMMENT 角色ID, PRIMARY KEY (user_id,role_id), KEY fk_role_id (role_id), CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES sys_user (id), CONSTRAINT fk_role_id FOREIGN KEY (role_id) REFERENCES sys_role (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户角色关联表;注意这里我们给用户名创建了唯一索引这是为了避免重复注册的问题。密码字段预留了 100 位长度因为 BCrypt 加密后的字符串通常在 60 位左右。2.2 项目依赖配置在pom.xml中添加必要的依赖!-- Spring Boot Starter Security -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-security/artifactId /dependency !-- Spring Boot Starter Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- MySQL驱动 -- dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency !-- MyBatis Plus -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.5/version /dependency !-- Lombok -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency为什么选择 MyBatis Plus因为它提供的 CRUD 接口可以帮我们减少 70% 的重复代码特别是BaseMapper中的方法完全能满足用户查询需求这也是很多企业开发的首选方案。2.3 数据源配置在application.yml中配置数据库连接信息spring: datasource: url: jdbc:mysql://localhost:3306/security_demo?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.example.securitydemo.entity configuration: map-underscore-to-camel-case: true # 开启驼峰命名转换这里有个细节需要注意MySQL 8.0 以上版本必须指定serverTimezone否则会出现时区错误。推荐使用Asia/Shanghai而不是UTC8因为在某些服务器环境下后者可能不被识别。核心实现自定义用户认证体系3.1 实体类设计创建与数据库表对应的实体类Data TableName(sys_user) public class SysUser { private Long id; private String username; private String password; private Boolean enabled; private LocalDateTime createTime; } Data TableName(sys_role) public class SysRole { private Long id; private String roleName; private String roleCode; }使用 Lombok 的Data注解可以省略 getter、setter 方法让代码更简洁。TableName注解指定对应的数据库表名这是 MyBatis Plus 的规范。3.2 Mapper 层实现创建用户和角色的 Mapper 接口public interface SysUserMapper extends BaseMapperSysUser { /** * 根据用户名查询用户角色 */ ListSysRole selectRolesByUsername(String username); }在resources/mapper目录下创建SysUserMapper.xml?xml version1.0 encodingUTF-8? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.example.securitydemo.mapper.SysUserMapper select idselectRolesByUsername resultTypecom.example.securitydemo.entity.SysRole SELECT r.id, r.role_name, r.role_code FROM sys_user u LEFT JOIN sys_user_role ur ON u.id ur.user_id LEFT JOIN sys_role r ON ur.role_id r.id WHERE u.username #{username} /select /mapper这个查询非常关键它通过用户 ID 关联角色表一次性获取用户拥有的所有角色信息这是实现基于角色的访问控制RBAC的基础。3.3 实现 UserDetailsService这是整个自定义认证中最核心的部分我们需要实现 Spring Security 提供的UserDetailsService接口Service RequiredArgsConstructor public class CustomUserDetailsService implements UserDetailsService { private final SysUserMapper sysUserMapper; Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1.查询用户信息 LambdaQueryWrapperSysUser queryWrapper new LambdaQueryWrapper(); queryWrapper.eq(SysUser::getUsername, username); SysUser user sysUserMapper.selectOne(queryWrapper); if (user null) { throw new UsernameNotFoundException(用户名不存在); } // 2.查询用户角色 ListSysRole roles sysUserMapper.selectRolesByUsername(username); ListString roleCodes roles.stream() .map(SysRole::getRoleCode) .collect(Collectors.toList()); // 3.转换为UserDetails对象 return User.withUsername(user.getUsername()) .password(user.getPassword()) .roles(roleCodes.toArray(new String[0])) .disabled(!user.getEnabled()) .build(); } }这段代码的执行流程是当用户登录时Spring Security 会调用loadUserByUsername方法我们首先从数据库查询用户信息如果用户不存在就抛出异常然后查询该用户的角色列表将角色编码转换为字符串数组最后构建User对象返回这个对象包含了用户名、密码、角色和启用状态等关键信息。3.4 配置 SecurityConfig创建安全配置类这是整合 Spring Security 的关键Configuration EnableWebSecurity RequiredArgsConstructor public class SecurityConfig { private final CustomUserDetailsService userDetailsService; Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize - authorize .requestMatchers(/login).permitAll() // 登录接口允许匿名访问 .requestMatchers(/admin/**).hasRole(ADMIN) // admin路径需要ADMIN角色 .requestMatchers(/user/**).hasAnyRole(ADMIN, USER) // user路径需要ADMIN或USER角色 .anyRequest().authenticated() // 其他请求需要认证 ) .formLogin(form - form .defaultSuccessUrl(/index, true) // 登录成功后跳转的页面 ) .logout(logout - logout .logoutSuccessUrl(/login?logout) // 退出登录后跳转的页面 ); return http.build(); } Bean public PasswordEncoder passwordEncoder() { // 使用BCrypt加密密码 return new BCryptPasswordEncoder(); } Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); } }这里我们做了几件重要的事情配置了 URL 访问权限登录接口允许匿名访问/admin/**路径需要 ADMIN 角色/user/**路径需要 ADMIN 或 USER 角色其他路径都需要认证后才能访问。配置了表单登录和退出登录的跳转页面这是 Web 应用最常用的登录方式。定义了PasswordEncoder为BCryptPasswordEncoder这是 Spring 官方推荐的密码加密方式它会自动生成随机盐值安全性非常高。暴露了AuthenticationManager方便我们在后续的控制器中处理登录逻辑。功能测试验证鉴权效果4.1 准备测试数据首先插入测试用户和角色-- 插入角色 INSERT INTO sys_role VALUES (1, 管理员, ADMIN); INSERT INTO sys_role VALUES (2, 普通用户, USER); -- 插入用户密码是123456加密后的结果 INSERT INTO sys_user VALUES (1, admin, $2a$10$Gd7QJ8dL9eXl8V6wLz5i5OQJQZJQZJQZJQZJQZJQZJQZJQZJQZ, 1, NOW()); INSERT INTO sys_user VALUES (2, user, $2a$10$Gd7QJ8dL9eXl8V6wLz5i5OQJQZJQZJQZJQZJQZJQZJQZJQZJQZ, 1, NOW()); -- 关联用户角色 INSERT INTO sys_user_role VALUES (1, 1); -- admin拥有ADMIN角色 INSERT INTO sys_user_role VALUES (2, 2); -- user拥有USER角色注意这里的密码是用BCryptPasswordEncoder加密后的结果原始密码都是 123456。如果你需要生成新的密码可以写一个简单的测试方法public class PasswordTest { public static void main(String[] args) { PasswordEncoder encoder new BCryptPasswordEncoder(); String password encoder.encode(123456); System.out.println(password); } }4.2 创建测试接口RestController public class TestController { GetMapping(/index) public String index(Authentication authentication) { return 欢迎 authentication.getName() 登录系统; } GetMapping(/admin/hello) public String adminHello() { return 管理员专属接口; } GetMapping(/user/hello) public String userHello() { return 用户专属接口; } }这些接口用于验证不同角色的访问权限/index任何登录用户都可以访问/admin/hello只有 ADMIN 角色可以访问/user/helloADMIN 和 USER 角色都可以访问4.3 测试场景验证未登录访问直接访问/index会被重定向到登录页面这符合我们的配置。user 用户登录可以访问/index和/user/hello访问/admin/hello会出现 403 错误提示权限不足admin 用户登录可以访问所有接口包括/admin/hello这说明角色权限控制生效了密码错误测试输入错误密码会提示 Bad credentials这是 Spring Security 的默认提示。用户不存在测试输入不存在的用户名会提示 用户名不存在这是我们在CustomUserDetailsService中自定义的异常信息。进阶优化提升安全性和可维护性5.1 密码加密存储最佳实践虽然我们已经使用了 BCrypt 加密但在实际开发中还有几点需要注意注册时加密用户注册时必须对密码进行加密处理绝对不能明文存储密码策略建议设置密码复杂度要求比如长度不少于 8 位包含大小写字母、数字和特殊符号定期更换可以在系统中添加密码定期更换提醒功能5.2 异常处理优化默认的异常信息不够友好我们可以自定义认证失败处理器Component public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler { Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException { response.setContentType(application/json;charsetutf-8); MapString, Object result new HashMap(); result.put(code, 401); if (exception instanceof UsernameNotFoundException) { result.put(msg, 用户名不存在); } else if (exception instanceof BadCredentialsException) { result.put(msg, 密码错误); } else { result.put(msg, 登录失败); } ObjectMapper mapper new ObjectMapper(); response.getWriter().write(mapper.writeValueAsString(result)); } }然后在SecurityConfig中配置.formLogin(form - form .defaultSuccessUrl(/index, true) .failureHandler(customAuthenticationFailureHandler) // 添加失败处理器 )这样前端就能得到结构化的错误信息方便进行友好提示。5.3 权限细化控制如果需要更细粒度的权限控制可以将角色Role和权限Permission分离实现基于权限的访问控制PBAC。基本思路是增加权限表和角色权限关联表在UserDetails中添加权限信息在配置中使用hasAuthority替代hasRole这种方式适合权限复杂的大型系统比如电商平台的后台管理系统。总结通过本文的学习我们已经掌握了在 Spring Boot3 中使用自定义数据库实现 Spring Security 鉴权的完整流程包括数据库设计和环境搭建自定义UserDetailsService实现用户信息查询配置SecurityConfig实现权限控制功能测试和进阶优化这套方案已经在很多实际项目中得到验证完全可以满足中小型系统的安全需求。对于大型系统你还可以在此基础上扩展集成 JWT 实现无状态认证添加验证码、记住我等功能对接 OAuth2.0 实现第三方登录集成 Spring Security OAuth2 实现分布式认证最后留一个思考题如果需要实现用户的动态权限调整不需要重启应用你会怎么做欢迎在评论区留下你的解决方案我们一起交流探讨。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

有没有做牛羊角的网站电影购买网站怎么设计

告别显示器控制烦恼:MonitorControl让你的Mac外接显示器更智能 【免费下载链接】MonitorControl MonitorControl/MonitorControl: MonitorControl 是一款开源的Mac应用程序,允许用户直接控制外部显示器的亮度、对比度和其他设置,而无需依赖原…

张小明 2026/1/18 18:30:03 网站建设

巩义网站建设案例课堂贵阳网站空间

FSNotes终极指南:简单高效的跨平台笔记管理解决方案 【免费下载链接】fsnotes Notes manager for macOS/iOS 项目地址: https://gitcode.com/gh_mirrors/fs/fsnotes 还在为笔记管理而烦恼吗?FSNotes为您提供完整的笔记管理体验!这款专…

张小明 2026/1/18 18:29:32 网站建设

设计网官方网站宜昌做网站的

城通网盘直连解析工具:3步实现高速下载体验 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 还在为城通网盘的下载限制而困扰吗?ctfileGet项目为您提供了一种全新的解决方案&…

张小明 2026/1/18 18:29:01 网站建设

网站开发敲代码wordpress成绩查询插件

Windows 10应用支持与性能调优全解析 1. Windows 10应用安装与部署 在Windows 10系统中,不同类型设备和应用的安装与部署方式各有不同。对于桌面计算机上的Windows应用商店应用,可使用配置管理器实现自动化安装。而对于手机、平板电脑以及未加入域的计算机,则可以借助移动…

张小明 2026/1/18 18:28:30 网站建设

健康养生网站源码查询网网站

第一章:教育AI Agent交互设计的核心挑战 在构建面向教育场景的AI Agent时,交互设计面临多重独特挑战。与通用对话系统不同,教育AI需要兼顾知识传递的准确性、学习者认知发展的阶段性以及教学过程的情感支持。这些因素共同构成了复杂而敏感的交…

张小明 2026/1/18 18:28:00 网站建设

网站开发简易软件电子商务的特点包括什么

积分兑换柜专业企业:黑云智能科技引领行业变革引言:在当今数字化时代,积分兑换作为一种常见的营销手段,越来越受到企业的重视。而积分兑换柜作为实现这一功能的重要载体,其专业性和高效性至关重要。黑云智能科技便是积…

张小明 2026/1/18 18:27:29 网站建设