档案管理软件的身份认证模块,常面临单点登录体验差、密码策略弱、多系统认证不统一等痛点。优化核心目标是:提升安全性、改善用户体验、实现统一认证管理。
对于大多数档案系统,推荐采用“中心化认证服务 + 多因素认证”的混合架构。认证服务独立部署,通过标准协议与档案软件交互。本文以广泛使用的 Keycloak(开源身份与访问管理)作为认证中心,档案软件后端基于Spring Boot为例,演示完整集成。
使用Docker快速部署一个Keycloak实例用于开发和测试。
```bash 拉取Keycloak镜像(使用Quarkus发行版,更轻量) docker pull quay.io/keycloak/keycloak:24.0.2 运行Keycloak容器 docker run -d \ --name keycloak \ -p 8080:8080 \ -e KEYCLOAK_ADMIN=admin \ -e KEYCLOAK_ADMIN_PASSWORD=your_strong_admin_password \ quay.io/keycloak/keycloak:24.0.2 start-dev ``` 注意:生产环境务必使用`start`命令替代`start-dev`,并配置数据库、TLS等。
容器启动后,访问 http://localhost:8080,使用设置的admin账户登录管理控制台。
在Spring Boot项目的`pom.xml`中,添加Keycloak适配器依赖。
```xml
在档案软件后端的`application.yml`或`application.properties`中,配置Keycloak连接信息。
```yaml server: port: 8081 档案软件后端端口 keycloak: realm: archive-realm auth-server-url: http://localhost:8080 Keycloak服务器地址 ssl-required: none 开发环境可设为none,生产必须为external或all resource: archive-backend 客户端ID credentials: secret: your_client_secret_here 替换为3.1步骤复制的Client Secret use-resource-role-mappings: true bearer-only: true 后端API服务,通常设置为true ```
创建一个Spring Security配置类,启用OAuth2资源服务器保护API端点。

```java import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver; import org.keycloak.adapters.springsecurity.KeycloakConfiguration; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper; import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy; import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy; @Configuration @KeycloakConfiguration @Import(KeycloakSpringBootConfigResolver.class) public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter { // 配置Keycloak认证提供者,将角色前缀从“ROLE_”映射去掉(Keycloak默认不带) @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider(); keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper()); auth.authenticationProvider(keycloakAuthenticationProvider); } @Bean @Override protected SessionAuthenticationStrategy sessionAuthenticationStrategy() { return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } @Override protected void configure(HttpSecurity http) throws Exception { super.configure(http); http .authorizeRequests() .antMatchers("/api/public/").permitAll() // 公开接口 .antMatchers("/api/admin/").hasRole("archive_admin") // 需要admin角色 .antMatchers("/api/user/").hasAnyRole("archive_admin", "archive_user") // 需要user或admin角色 .anyRequest().authenticated() // 其他所有请求需要认证 .and() .oauth2ResourceServer() // 启用OAuth2资源服务器 .jwt(); // 使用JWT令牌 } } ```
在需要受保护的API控制器中,可以使用Spring Security注解进行方法级权限控制。
```java import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.; @RestController @RequestMapping("/api") public class ArchiveController { @GetMapping("/admin/dashboard") @PreAuthorize("hasRole('archive_admin')") // 方法级角色检查 public String adminDashboard() { return "Admin Dashboard Data"; } @PostMapping("/user/upload") @PreAuthorize("hasAnyRole('archive_admin', 'archive_user')") public String uploadFile(@RequestBody FileRequest request) { // 处理文件上传逻辑 return "Upload Success"; } } ```
前端(以React为例)使用`oidc-client-js`库处理登录。首先安装库:`npm install oidc-client-js`。
创建认证服务文件`authService.js`:
```javascript import { UserManager, WebStorageStateStore } from 'oidc-client-js'; const config = { authority: 'http://localhost:8080/realms/archive-realm', // Keycloak realm地址 client_id: 'archive-frontend', // 需要在Keycloak为前端单独创建一个客户端,Access Type为public redirect_uri: 'http://localhost:3000/callback', // 前端回调地址 response_type: 'code', scope: 'openid profile email', post_logout_redirect_uri: 'http://localhost:3000/', userStore: new WebStorageStateStore({ store: window.localStorage }), }; const userManager = new UserManager(config); export const login = () => userManager.signinRedirect(); export const logout = () => userManager.signoutRedirect(); export const getUser = () => userManager.getUser(); export const handleCallback = () => userManager.signinRedirectCallback(); // 在应用初始化时(如App.js的useEffect中)检查登录状态 // getUser().then(user => { if (user) { // 已登录,将token存入axios请求头 } else { // 未登录 } }); ```
关键步骤:前端需要访问受保护API时,将获取到的access token放入HTTP请求的Authorization头:`Authorization: Bearer
后端收到带Bearer Token的请求后,Spring Security会自动通过Keycloak的JWKS端点验证令牌签名和有效性。你可以在控制器中注入`Jwt`对象来获取令牌内的用户信息。
```java
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
@GetMapping("/api/me")
public Map
完成以上步骤后,用户登录时在输入密码后,会强制要求输入由Google Authenticator等应用生成的6位动态验证码。用户首次登录时,Keycloak会提供二维码和密钥,用于在手机App中绑定账户。
通过以上步骤,你已将档案软件的身份认证升级为基于开源标准、支持单点登录、具备多因素认证能力的现代化体系。所有配置均可直接复制使用,只需替换其中的服务器地址、域名和密钥信息即可适配你的生产环境。