Java中的授权与认证:核心概念与工具
认证和授权是任何Web应用程序安全的两大基石。在Java生态系统中,有许多成熟的库和框架可用于处理这些任务。本文将详细解析关键工具、它们的特点,并提供实用的代码示例。
1. 基本概念
在介绍工具之前,明确区分这两个术语非常重要:
- 认证 — 验证用户身份(您是谁?)。通常通过登录名/密码、令牌或生物识别来完成。
- 授权 — 验证访问权限(您被允许做什么?)。决定用户是否可以执行特定操作。
2. Spring Security — 事实标准
Spring Security 是Java应用程序中最流行的安全框架。它为认证和授权提供了全面的解决方案。
2.1. 基本认证配置
要引入Spring Security,请在 pom.xml 中添加依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId></dependency>使用内存认证的最小配置:
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.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.provisioning.InMemoryUserDetailsManager;import org.springframework.security.web.SecurityFilterChain;
@Configurationpublic class SecurityConfig {
@Bean public InMemoryUserDetailsManager userDetailsManager() { UserDetails user = User.withDefaultPasswordEncoder() .username("user") .password("password") .roles("USER") .build(); return new InMemoryUserDetailsManager(user); }
@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(authz -> authz .requestMatchers("/admin/**").hasRole("ADMIN") .requestMatchers("/user/**").hasRole("USER") .anyRequest().authenticated() ) .formLogin(login -> login.defaultSuccessUrl("/home")) .httpBasic(); return http.build(); }}3. JWT(JSON Web令牌)用于无状态认证
JWT允许实现无服务器端状态的认证。令牌包含所有必要的用户信息,并使用密钥进行签名。
3.1. 使用 jjwt 库生成JWT
添加依赖:
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.12.5</version></dependency>创建和验证令牌的示例:
import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import io.jsonwebtoken.security.Keys;import javax.crypto.SecretKey;import java.util.Date;
public class JwtUtil {
private static final SecretKey SECRET_KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256); private static final long EXPIRATION_TIME = 3600000; // 1小时
public static String generateToken(String username) { return Jwts.builder() .setSubject(username) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTi