authentication.getPrincipal()为什么总是返回username而不是UserDetails的实现类

authentication.getPrincipal()为什么总是返回username而不是UserDetails的实现类

关于这个问题在网上找了很多,有说需要实现UserDetailsService,也有说要改源码,感觉都不靠谱,决定自己解决问题。

getPrincipal是Authentication接口下的一个方法,而getPrincipal方法有以下几个实现
在这里插入图片描述
经过断点调试,发现走的UsernamePasswordAuthenticationToken类中的实现方法,但是这个方法实现只是简单返回了principal这个属性,看不出什么东西
在这里插入图片描述
既然是对象的属性,那么再找找这个类的构造方法,发现UsernamePasswordAuthenticationToken的构造方法有两个
在这里插入图片描述
继续排查这两个构造方法的引用情况,发现其中一个构造方法被我们使用到
在这里插入图片描述
问题到这里已经很明显了,大概率是我们自定义的权限验证出了问题,查看SecurityAuthenticationProvider的authenticate方法

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        // 自定义的验证逻辑
        final String username = String.valueOf(authentication.getPrincipal());
        final String password = String.valueOf(authentication.getCredentials());
        Set<GrantedAuthority> authorities = new HashSet<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        UserEntity userEntity = new UserEntity();
        userEntity.setUsername(username);
        userEntity.setPassword(password);
        userEntity.setAuthorities(authorities);
        // 返回UsernamePasswordAuthenticationToken对象
        return new UsernamePasswordAuthenticationToken(username, password, authorities);
    }

关注返回的对象

return new UsernamePasswordAuthenticationToken(username, password, authorities);

所用的构造器传入的第一个参数是username,看上面的构造方法代码不难发现这就是principal属性的值,所以,只需要改为

return new UsernamePasswordAuthenticationToken(userEntity, password, authorities);

至此,问题解决。

总结

关注SecurityAuthenticationProvider的authenticate方法的返回值,你返回什么,authentication.getPrincipal()就得到什么,很合理!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spring Boot可以使用JSON Web Token(JWT)实现登录令牌。 JWT包括三个部分:头部,载荷和签名。头部包括JWT型和算法,载荷包括用户信息和过期时间,签名用于验证JWT的完整性。 下面是一个示例JWT实现: 1. 添加依赖 在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> ``` 2. 创建JWT工具 创建一个JWT工具,用于生成和验证JWT: ``` public class JwtUtils { private static final String SECRET_KEY = "secret"; private static final long EXPIRATION_TIME = 86400000; // 24 hours public static String generateToken(UserDetails userDetails) { Map<String, Object> claims = new HashMap<>(); claims.put("username", userDetails.getUsername()); claims.put("authorities", userDetails.getAuthorities()); return Jwts.builder() .setClaims(claims) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512, SECRET_KEY) .compact(); } public static boolean validateToken(String token, UserDetails userDetails) { Claims claims = Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); String username = claims.get("username", String.class); List<GrantedAuthority> authorities = (List<GrantedAuthority>) claims.get("authorities"); return username.equals(userDetails.getUsername()) && authorities.equals(userDetails.getAuthorities()); } } ``` 3. 在登录控制器中生成JWT 在登录控制器中生成JWT并返回给客户端: ``` @PostMapping("/login") public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) { Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()) ); SecurityContextHolder.getContext().setAuthentication(authentication); String token = JwtUtils.generateToken((UserDetails) authentication.getPrincipal()); return ResponseEntity.ok(new JwtResponse(token)); } ``` 4. 在资源控制器中验证JWT 在资源控制器中验证JWT: ``` @GetMapping("/resource") public ResponseEntity<?> getResource(@RequestHeader("Authorization") String authorizationHeader) { String token = authorizationHeader.replace("Bearer ", ""); if (!JwtUtils.validateToken(token, (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal())) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } // do something with the resource return ResponseEntity.ok("Resource accessed successfully"); } ``` 以上就是使用Spring Boot和JWT实现登录令牌的示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值