本文目录导读:

- 最基础:基于 Session 的简单认证(Servlet/JSP)
- 前后端分离:基于 Token(JWT)的认证
- 企业级标准:Spring Security + JWT
- 选择建议
- 关键安全注意事项
- 完整示例代码结构
在Java中实现登录认证,根据项目规模和复杂度,有多种实现方式,以下从基础原理到企业级框架,分层次介绍几种典型的实现案例。
最基础:基于 Session 的简单认证(Servlet/JSP)
这是最原始的方式,适用于理解认证核心流程。
核心原理
- 用户提交用户名和密码
- 服务器验证凭据
- 验证成功,将用户信息存入
HttpSession - 后续请求检查
Session中是否有用户信息
代码示例
LoginServlet.java
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
// 硬编码校验(实际应查询数据库)
if ("admin".equals(username) && "123456".equals(password)) {
// 登录成功,存入 Session
HttpSession session = req.getSession();
session.setAttribute("user", username);
resp.sendRedirect("/home.jsp");
} else {
req.setAttribute("error", "用户名或密码错误");
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}
}
AuthFilter.java(拦截器保护资源)
@WebFilter("/home.jsp")
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession(false);
if (session == null || session.getAttribute("user") == null) {
req.setAttribute("error", "请先登录");
req.getRequestDispatcher("/login.jsp").forward(request, response);
} else {
chain.doFilter(request, response); // 放行
}
}
}
特点:简单直接,但不适用于分布式/前后端分离,Session 依赖服务器内存。
前后端分离:基于 Token(JWT)的认证
现代 Web 应用(Vue/React + Spring Boot)最常用。
核心流程
- 用户登录 → 服务端验证 → 签发 JWT
- 前端将 JWT 存在
localStorage或cookie中 - 每次请求在
Authorization头携带 JWT - 过滤器解析 JWT,提取用户信息放入安全上下文
Java 案例(Spring Boot + JJWT)
添加依赖(Maven)
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.5</version>
<scope>runtime</scope>
</dependency>
JWT 工具类
public class JwtUtil {
private static final String SECRET = "your-256-bit-secret-key-change-in-production";
private static final long EXPIRATION = 86400000L; // 24小时
// 生成 Token
public static String generateToken(String username) {
return Jwts.builder()
.subject(username)
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + EXPIRATION))
.signWith(SignatureAlgorithm.HS256, SECRET)
.compact();
}
// 解析 Token
public static String parseToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET)
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
// 验证 Token 有效性
public static boolean isValid(String token) {
try {
parseToken(token);
return true;
} catch (Exception e) {
return false;
}
}
}
登录接口
@PostMapping("/api/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
// 1. 验证用户名密码(查询数据库,这里简单模拟)
if ("admin".equals(loginRequest.getUsername()) && "123456".equals(loginRequest.getPassword())) {
// 2. 生成 JWT
String token = JwtUtil.generateToken(loginRequest.getUsername());
// 3. 返回 Token
return ResponseEntity.ok(new JwtResponse(token, "登录成功"));
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("用户名或密码错误");
}
JWT 过滤器(Spring Security 方式见下节)
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.substring(7);
if (JwtUtil.isValid(token)) {
String username = JwtUtil.parseToken(token);
// 将用户信息放入 SecurityContext(用于后续控制器获取)
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(username, null, null);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(request, response);
}
}
前端配合(Vue/React 示例)
// 登录成功后存储 Token
localStorage.setItem('token', response.data.token);
// Axios 拦截器自动携带 Token
axios.interceptors.request.use(config => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
特点:无状态、分布式友好、前后端解耦。
企业级标准:Spring Security + JWT
Spring Security 提供了完整的认证授权框架,学习曲线略高,但功能强大。
核心配置
SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // 前后端分离需关闭 CSRF
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 无状态
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/login", "/api/register").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // 密码加密
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
}
UserDetailsService 实现(数据库查用户)
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("用户不存在"));
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList())
);
}
}
登录接口(使用 AuthenticationManager)
@RestController
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/api/login")
public ResponseEntity<?> login(@RequestBody LoginRequest request) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
);
// 认证成功,生成 Token
String token = jwtUtil.generateToken(authentication.getName());
return ResponseEntity.ok(new JwtResponse(token));
}
}
选择建议
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 单体应用、课后作业 | Session 认证 | 简单,无需额外依赖 |
| 前后端分离、Vue/React+Spring Boot | JWT 自定义过滤器 | 轻量,足够用 |
| 大型企业项目、多角色/权限复杂 | Spring Security + JWT | 标准、可扩展、社区支持好 |
| 微服务架构 | OAuth2 + JWT + Spring Security | 统一认证中心 |
关键安全注意事项
- 密码存储:永远不要明文存储密码,使用
BCrypt、Argon2等密码哈希算法。 - HTTPS:生产环境必须使用 HTTPS,防止 Token 被中间人窃取。
- JWT 过期:设置合理的过期时间(建议 15-30 分钟),配合 Refresh Token 实现长期登录。
- XSS/CSRF:Token 不要放在容易被注入的 localStorage(可放 HttpOnly Cookie 配合 CSRF Token)。
- 权限校验:不仅是登录认证,每个接口还需要检查用户是否拥有对应操作权限(RBAC)。
完整示例代码结构
project/
├── config/
│ └── SecurityConfig.java // Spring Security 配置
├── filter/
│ └── JwtAuthenticationFilter.java
├── util/
│ └── JwtUtil.java // JWT 工具类
├── controller/
│ └── AuthController.java // 登录/注册接口
├── service/
│ ├── UserService.java
│ └── CustomUserDetailsService.java
├── model/
│ └── User.java
└── repository/
└── UserRepository.java
如果你有具体的项目框架需求(Spring Boot + Vue 的完整项目),我可以进一步给出更详细的实现代码。