• Spring Security 注解AuthenticationPrincipal 失效排查


    #背景
    项目使用了springframework.security

    接口入参使用了springframework.security 注解 @AuthenticationPrincipal

     /**
         * 获得个人资料
         */
        @PostMapping(value = "/getUserPersonalInfo", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
        @PermissionCheck(value = "ROLE_USER")
        public String getUserPersonalInfo(@AuthenticationPrincipal Principal principal){
            String username = principal.getName();
            try {
                DataMap data = userService.getUserPersonalInfoByUsername(username);
                return JsonResult.build(data).toJSON();
            } catch (Exception e){
                log.error("[{}] get user personal info exception", username, e);
            }
            return JsonResult.fail(CodeType.SERVER_EXCEPTION).toJSON();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    注解失效,前端请求接口的时候发现

    Principal 为空

    问题排查

    这个问题不复杂, String username = principal.getName();NPE

    spring security 框架未处理 principal.setName() 的逻辑,具体代码位置不分析了,

    一般分布式项目很少使用 security 框架,基本上都是基于jwt + redis 实现分布式登录验证,验证的逻辑放在网关里。

    怎么解决

    排查了 注解 @AuthenticationPrincipal 使用方法

    发现一篇文件介绍 spring security 怎么获取用户的登录信息

    发现了新的主键:

    @CurrentSecurityContext

    用法:

    
        /**
         * 获得个人资料
         */
        @PostMapping(value = "/getUserPersonalInfo", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
        @PermissionCheck(value = "ROLE_USER")
        public String getUserPersonalInfo(@CurrentSecurityContext(expression = "authentication")  Authentication authentication){
            String username =authentication.getName();
            try {
                DataMap data = userService.getUserPersonalInfoByUsername(username);
                return JsonResult.build(data).toJSON();
            } catch (Exception e){
                log.error("[{}] get user personal info exception", username, e);
            }
            return JsonResult.fail(CodeType.SERVER_EXCEPTION).toJSON();
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    这个是经过2这个小时的排查的结果

    期间 使用了简单直接的方法获取用户信息

      Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            String loginName = auth.getName();
    
    • 1
    • 2

    想着如果spring security 框架没有自己处理,是不是自己写一个拦截器处理,或者是不是需要自己实现spring security 中自定义拦截器
    后边发现或许是项目中的 spring security 版本升级导致,查看了maven 中的版本已经升级到了5.0

    参考资料:参考资料一

    参考资料二

    转载于:https://www.fancv.com/article/1661265334

  • 相关阅读:
    机器学习——特征工程和评价指标
    SQL 基础入门教程
    Qt调用工业相机之海康威视相机SDK配置(完整版)
    基础数学知识
    面试题-7
    css和js放置的位置
    Windows如何启动MySQL
    【OpenGauss 列存储学习总结 2】
    「大厂必备」系列之Redis主从、持久化、哨兵
    LeetCode每日一题(2447. Number of Subarrays With GCD Equal to K)
  • 原文地址:https://blog.csdn.net/keep_learn/article/details/126494315