登录功能实现深度解析:从会话管理到安全校验全流程指南

大家好,我是凯哥Java

本文标签:登录验证流程、过滤器与拦截器、安全防护措施

image.png

简介

本文深入探讨了从登录功能实现到会话管理和安全校验的全流程,包括参数校验、身份验证、令牌生成和存储等关键步骤。通过比较主流的会话技术(如Cookie、Session和JWT),并详细讲解过滤器与拦截器的区别及其应用场景,提供了构建高性能、高安全性Web应用的具体指导。

一、登录功能核心实现流程

1.1 登录流程图解

image.png

1.2 关键实现步骤

  • 参数校验层:验证用户名/邮箱格式、密码强度

  • 身份验证层:数据库查询+密码哈希比对

  • 令牌生成层:使用JWT生成访问令牌和刷新令牌

  • 令牌存储层:Redis缓存令牌实现快速验证

  • 安全传输层:HTTPS+HttpOnly Cookie保障传输安全

二、会话跟踪技术深度对比

2.1 主流会话技术对比

技术类型CookieSessionJWT
存储位置客户端服务端客户端
安全性较低较高较高(需HTTPS)
扩展性单域限制集群部署需同步天然支持分布式
性能开销中等
典型应用场景简单状态保持传统Web应用前后端分离/移动端

2.2 JWT令牌技术详解

令牌结构示例

// Header

{

  "alg": "HS256",

  "typ": "JWT"

}

// Payload

{

  "sub": "1234567890",

  "name": "John Doe",

  "iat": 1516239022,

  "exp": 1516242622

}

// Signature

HMACSHA256(

  base64UrlEncode(header) + "." +

  base64UrlEncode(payload),

  secret)

Java生成JWT示例

public String generateToken(UserDetails userDetails) {

    Map<String, Object> claims = new HashMap<>();

    claims.put("roles", userDetails.getAuthorities());

    

    return Jwts.builder()

        .setClaims(claims)

        .setSubject(userDetails.getUsername())

        .setIssuedAt(new Date(System.currentTimeMillis()))

        .setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000))

        .signWith(SignatureAlgorithm.HS256, secretKey)

        .compact();

}

三、安全校验实现方案

3.1 过滤器(Filter)实现方案

public class JwtFilter implements Filter {

    @Override

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 

        throws IOException, ServletException {

        

        HttpServletRequest request = (HttpServletRequest) req;

        String token = resolveToken(request);

        

        if (StringUtils.hasText(token) && validateToken(token)) {

            Authentication auth = parseAuthentication(token);

            SecurityContextHolder.getContext().setAuthentication(auth);

        }

        

        chain.doFilter(req, res);

    }

    private String resolveToken(HttpServletRequest request) {

        String bearerToken = request.getHeader("Authorization");

        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {

            return bearerToken.substring(7);

        }

        return null;

    }

}

3.2 拦截器(Interceptor)实现方案

public class JwtInterceptor implements HandlerInterceptor {

    

    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 

        throws Exception {

        

        if (!(handler instanceof HandlerMethod)) return true;

        String token = getTokenFromRequest(request);

        if (token == null || !jwtProvider.validateToken(token)) {

            throw new AuthenticationException("Invalid JWT token");

        }

        

        setAuthentication(token);

        return true;

    }

    private String getTokenFromRequest(HttpServletRequest request) {

        // 从Cookie或Header获取令牌

    }

}

3.3 过滤器与拦截器对比

image.png

四、全局异常处理机制

4.1 异常处理类实现

@RestControllerAdvice

public class GlobalExceptionHandler {

    

    @ExceptionHandler(AuthenticationException.class)

    public ResponseEntity<ErrorResponse> handleAuthException(AuthenticationException ex) {

        ErrorResponse error = new ErrorResponse();

        error.setStatus(HttpStatus.UNAUTHORIZED.value());

        error.setMessage("Authentication failed: " + ex.getMessage());

        error.setTimestamp(LocalDateTime.now());

        return new ResponseEntity<>(error, HttpStatus.UNAUTHORIZED);

    }

    @ExceptionHandler(AccessDeniedException.class)

    public ResponseEntity<ErrorResponse> handleAccessDenied(AccessDeniedException ex) {

        ErrorResponse error = new ErrorResponse();

        error.setStatus(HttpStatus.FORBIDDEN.value());

        error.setMessage("Access denied: " + ex.getMessage());

        return new ResponseEntity<>(error, HttpStatus.FORBIDDEN);

    }

}

4.2 错误响应DTO

@Data

@AllArgsConstructor

@NoArgsConstructor

public class ErrorResponse {

    private int status;

    private String message;

    private LocalDateTime timestamp;

    private String path;

    

    public ErrorResponse(HttpStatus status, String message, String path) {

        this.status = status.value();

        this.message = message;

        this.timestamp = LocalDateTime.now();

        this.path = path;

    }

}

五、安全增强最佳实践

5.1 令牌刷新机制

public TokenPair refreshToken(String refreshToken) {

    if (!validateRefreshToken(refreshToken)) {

        throw new InvalidTokenException("Invalid refresh token");

    }

    

    String username = parseUsername(refreshToken);

    UserDetails user = userService.loadUserByUsername(username);

    

    String newAccessToken = generateAccessToken(user);

    String newRefreshToken = generateRefreshToken(user);

    

    redisTemplate.delete(refreshToken);

    redisTemplate.opsForValue().set(newRefreshToken, username, REFRESH_EXPIRE);

    

    return new TokenPair(newAccessToken, newRefreshToken);

}

5.2 并发登录控制

public void handleConcurrentLogin(String username, String newSessionId) {

    String oldSession = redisTemplate.opsForValue().get("user:" + username);

    if (StringUtils.hasText(oldSession)) {

        // 1. 发送下线通知

        messagingTemplate.convertAndSendToUser(oldSession, "/queue/logout", "forced_logout");

        // 2. 清除旧令牌

        redisTemplate.delete(oldSession);

    }

    // 3. 存储新会话

    redisTemplate.opsForValue().set("user:" + username, newSessionId);

}

六、性能优化方案

6.1 令牌验证优化

public boolean validateToken(String token) {

    // 先检查黑名单

    if (redisTemplate.hasKey("token:blacklist:" + token)) {

        return false;

    }

    

    // 快速过期检查

    if (Jwts.parser().parseClaimsJws(token).getBody().getExpiration().before(new Date())) {

        return false;

    }

    

    // 详细验证

    try {

        Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);

        return true;

    } catch (JwtException e) {

        return false;

    }

}

6.2 缓存策略设计

@Cacheable(value = "userDetails", key = "#username")

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

    User user = userRepository.findByUsername(username)

        .orElseThrow(() -> new UsernameNotFoundException("User not found"));

    

    return new CustomUserDetails(

        user.getUsername(),

        user.getPassword(),

        getAuthorities(user.getRoles())

    );

}

@CacheEvict(value = "userDetails", key = "#user.username")

public void updateUser(User user) {

    userRepository.save(user);

}

七、安全防护措施

7.1 常见攻击防护

image.png

7.2 安全头配置

@Configuration

public class SecurityHeaderConfig implements WebMvcConfigurer {

    

    @Override

    public void addCorsMappings(CorsRegistry registry) {

        registry.addMapping("/**")

            .allowedOrigins("https://yourdomain.com")

            .allowedMethods("GET", "POST")

            .allowCredentials(true);

    }

    @Bean

    public FilterRegistrationBean<HeaderFilter> securityHeadersFilter() {

        FilterRegistrationBean<HeaderFilter> registration = new FilterRegistrationBean<>();

        registration.setFilter(new HeaderFilter());

        registration.addUrlPatterns("/*");

        return registration;

    }

    private static class HeaderFilter extends OncePerRequestFilter {

        @Override

        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, 

            FilterChain filterChain) throws ServletException, IOException {

            

            response.setHeader("X-Content-Type-Options", "nosniff");

            response.setHeader("X-Frame-Options", "DENY");

            response.setHeader("X-XSS-Protection", "1; mode=block");

            response.setHeader("Content-Security-Policy", "default-src 'self'");

            

            filterChain.doFilter(request, response);

        }

    }

}

八、监控与日志

8.1 登录审计日志

@Aspect

@Component

public class LoginAuditAspect {

    

    @Autowired

    private AuditLogService auditLogService;

    @AfterReturning(pointcut = "execution(* AuthController.login(..))", returning = "result")

    public void logSuccessLogin(JoinPoint joinPoint, Object result) {

        Object[] args = joinPoint.getArgs();

        String username = (String) args[0];

        auditLogService.log(username, "LOGIN_SUCCESS", "User logged in successfully");

    }

    @AfterThrowing(pointcut = "execution(* AuthController.login(..))", throwing = "ex")

    public void logFailedLogin(JoinPoint joinPoint, Exception ex) {

        Object[] args = joinPoint.getArgs();

        String username = (String) args[0];

        auditLogService.log(username, "LOGIN_FAILED", ex.getMessage());

    }

}

8.2 监控指标

@Configuration

public class SecurityMetricsConfig {

    @Bean

    public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {

        return registry -> registry.config().commonTags(

            "application", "auth-service",

            "region", System.getenv("REGION")

        );

    }

    @Bean

    public TimedAspect timedAspect(MeterRegistry registry) {

        return new TimedAspect(registry);

    }

    @Bean

    public Counter loginAttemptCounter(MeterRegistry registry) {

        return Counter.builder("auth.login.attempts")

            .description("Total login attempts")

            .register(registry);

    }

}

九、总结与选型建议

9.1 技术选型矩阵

image.png

9.2 性能优化checklist

  • 启用JWT压缩(特别是包含大量claims时)

  • 使用非对称加密算法(RS256)替代HS256

  • 实现令牌黑名单的自动过期清理

  • 配置合理的会话超时时间

  • 启用HTTP/2提升传输效率

  • 使用CDN加速静态资源访问

通过本文的详细实现方案,大家可以构建出更加安全可靠、高性能的登录认证系统。建议根据实际业务需求选择合适的会话管理方案,并持续监控系统安全指标。

  1. JWT令牌生成指南

  2. Redis在会话管理中的作用

  3. Spring Security过滤器配置

  4. Web应用常见攻击防御策略

  5. 基于OAuth2的微服务认证

作者:凯哥Java

日期:2025年07月17日

标签:登录验证流程、令牌管理与安全、会话跟踪技术、过滤器与拦截器、安全防护措施

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/89540.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/89540.shtml
英文地址,请注明出处:http://en.pswp.cn/web/89540.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023 年 5 月青少年软编等考 C 语言六级真题解析

目录 T1. 字符串插入 思路分析 T2. 机器翻译 思路分析 T3. 栈基本操作 思路分析 T4. 双端队列 思路分析 T1. 字符串插入 题目链接:SOJ D1138 有两个字符串 s t r str str 和 s u b s t r substr substr, s t r str str 的字符个数不超过 10 10 10, s u b s t r substr …

Redux架构解析:状态管理的核心原理

Redux 作为 JavaScript 应用的状态管理库&#xff0c;其技术架构与核心原理围绕​​可预测的状态管理​​设计&#xff0c;通过严格的单向数据流和函数式编程理念实现复杂应用的状态控制。以下从设计理念、核心架构、工作流程、源码实现等角度进行系统性剖析&#xff1a;一、设…

linux制作镜像、压缩镜像、烧录的方法

最近在玩香橙派的时候&#xff0c;需要搞多个板子&#xff0c;一个一个配环境也太麻烦了吧......于是通过搜索&#xff0c;发现可以把linux设备&#xff08;比如香橙派&#xff0c;树莓派等等&#xff09;制作为镜像&#xff0c;然后像烧录官方镜像一样烧进新的sd卡&#xff0c…

机械材料计算软件,快速核算重量

软件介绍 今天为大家推荐一款专为机械行业设计人员打造的金属材料重量计算软件&#xff0c;帮助工程师快速完成材料重量核算。 软件特点 这款绿色版计算工具体积小巧&#xff0c;不足100KB&#xff0c;无需安装即可直接运行&#xff0c;不占用系统资源&#xff0c;特别适…

Chrome更新后,扩展不能用问题

Chrome更新后&#xff0c;扩展不能用问题 此扩展程序不再受支持&#xff0c;因此已停用 在 Windows 10/11 搜索框中输入 regedit 打开 注册表编辑器 在注册表编辑器中打开&#xff1a;HKEYLOCALMACHINE\SOFTWARE\Policies\ 右键单击 Policies 新建项 命名为 Google 右键单…

【Python】通过cmd的shell命令获取局域网内所有IP、MAC地址,通过主机名获取IP

【Python】通过cmd的shell命令获取局域网内所有IP、MAC地址&#xff0c;通过主机名获取IP 更新以gitee为准&#xff1a; gitee 文章目录cmd命令获取IPping主机名获取IP的主机名socket获取当前网关运行效果附录&#xff1a;列表的赋值类型和py打包列表赋值BUG复现代码改进优化总…

sky-take-out项目Mybatis的使用

分页查询public PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) {PageHelper.startPage(categoryPageQueryDTO.getPage(),categoryPageQueryDTO.getPageSize());//下一条sql进行分页&#xff0c;自动加入limit关键字分页Page<Category> page categor…

H3CNE小小综合实验

实验拓扑图实验需求 按照图示配置IP地址在SW1和SW2之间配置链路聚合增加链路带宽&#xff0c;提高可靠性PC5和PC6属于VLAN10&#xff0c; PC7和PC8属于VLAN20SW1和SW2属于二层交换机&#xff0c;SW3为三层交换机&#xff08;VLAN100用于对接R4&#xff09;,在交换机之间相连的链…

IP协议深入理解

一、什么是ip协议?1.1、ip协议是网络层协议&#xff0c;ip协议的本质工作是提供一种能力&#xff0c;把数据可靠的跨网络从主机A送到主机B&#xff1b;1.2、什么是ip&#xff1f;ip目标网络目标主机&#xff1b;画图图解:如图&#xff0c;当主机A想要把数据发给主机B时&#x…

接收表单数据:serialize()函数解析

一、form-serialize作用与引入 作用&#xff1a; form-serialize可以快速收集表单数据&#xff0c;按照使用者意愿转化为对象或字符串输出&#xff0c;以便于提交至服务器。 引入&#xff1a; form-serialize不是浏览器自带的JS方法&#xff0c;而是第三方工具库。可以直接通过…

vc配置使用预编译

预编译原理 stdafx.h中加入系统文件&#xff0c;减少cpp中对这些文件的解析&#xff0c;提高速度 stdafx.h 会把编译的文件生成pch&#xff0c;后续解析头文件直接调用pch里面的数据 配置 新建stdafx.h和stdafx.cpp文件 配置stdafx.cpp文件为/Yc 创建预编译文件整个项目设置/Yc…

反射机制的登录系统

一、实体层&#xff08;po层&#xff09; //UserInfo package com.hugeyurt.po;import java.sql.ResultSet; import java.sql.SQLException;public class UserInfo {private String userID;private String name;private int count;private Long errorTime;private String pwd;p…

装饰器模式及优化

装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构。这种模式创建了一个装饰器类&#xff0c;用来包装原有的类&#xff0c;并在保持类方法签名完整性的前提下&#xff…

共指消解技术全解析:从语言学规则到深度学习(附论文精读)

精读威斯康星大学综述《Coreference Resolution: A Survey》&#xff0c;揭秘NLP中"实体链接"的核心技术一、什么是共指消解&#xff1f;为什么它是NLP的基石&#xff1f;共指消解(Coreference Resolution) 旨在识别文本中指向同一实体的不同表述。例如&#xff1a;t…

git配置git commit -m “fix 11,22: 修改bugid为11,22“

文章目录前言一、报错提示二、实现1.commitlint.config.js规范配置2. **修改正则表达式**&#xff1a;3. **移除 scope-case 规则**&#xff1a;4. **增强自定义规则逻辑**&#xff1a;测试结果&#xff1a;正则表达式详解&#xff1a;前言 提示&#xff1a;正常的配置git规范…

nastools继任者?极空间部署影视自动化订阅系统『MediaMaster』

nastools继任者&#xff1f;极空间部署影视自动化订阅系统『MediaMaster』 哈喽小伙伴们好&#xff0c;我是Stark-C~ 对于我们NAS玩家来说&#xff0c;观影总是大家绕不开的一个执念&#xff0c;并且为观影的折腾大家也都是乐此不疲~ 曾经有一个非常绝绝子的观影神器摆在我们…

题解:CF1690G Count the Trains

思路&#xff1a; 首先我们可以理清一下各种情况&#xff1a;1&#xff09;m可能为02&#xff09;一次操作时&#xff0c;只需要考虑每节火车的车头。3&#xff09;当一节火车的速度降低时&#xff0c;只会影响它及它后面的车厢当m0时&#xff0c;我们可以记录上一节车头的速度…

CCF编程能力等级认证GESP—C++3级—20250628

CCF编程能力等级认证GESP—C3级—20250628单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09;判断题&#xff08;每题 2 分&#xff0c;共 20 分&#xff09;编程题 (每题 25 分&#xff0c;共 50 分)奇偶校验分糖果单选题&#xff08;每题 2 分&#xff0c;共 30 分…

2G和3G网络关闭/退网状态(截止2025年7月)

从能打语音电话的2G&#xff0c;到能发彩信、聊QQ的3G&#xff0c;这两项陪伴了我们数十年的通信技术&#xff0c;正在悄然退出历史舞台。近日&#xff0c;全球移动供应商协会&#xff08;GSA&#xff09;发布的《2025年7月2G和3G网络关闭报告》显示&#xff0c;全球已有超百个…

Day06_C语言网络编程20250718mobus重点

01.思维导图1 什么是 modbus他是一个在工控领域非常好用的通信写 modbus协议本质上是一个 基于 tcp 协议二次封装的一个协议 什么叫做基于tcp二次封装的协议&#xff1a;我们自己写的pack_t(无论静态还是动态)&#xff0c;都是属于二次封装的协议modbus协议是一种 “主从问答式…