当前位置: 首页 > 知识库问答 >
问题:

Spring OAuth with JWT custom UserDetails-在JwtAccessTokenConverter中设置主体

郝峰
2023-03-14

一些额外的信息是从OAuth授权服务器发送的,这些信息是在资源服务器上的自定义类中需要的,最好是在SpringSecurity主体中。

当前的方法是将用户名设置为主体,并添加其他信息作为身份验证对象的附加详细信息,如下所示。

public class CustomAccessTokenConverter extends JwtAccessTokenConverter{

    @Override
    public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
        OAuth2Authentication authentication = super.extractAuthentication(claims);

        CustomUserDetails userDetails = new CustomUserDetails ();
        userDetails.setUserId(((Integer)claims.get("id")).longValue());
        userDetails.setName((String) claims.get("name"));
        userDetails.setLastName((String) claims.get("lastName"));

        authentication.setDetails(userDetails);

        return authentication;
    }
}

这种方法的好处是我们可以从应用程序内的任何位置访问自定义用户详细信息。坏消息是Pricipal对象仅限于用户用户名,我们需要更多代码来访问自定义用户详细信息。

// preferable way   
(UserAuthDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

// current solution
(UserAuthDetails) ((OAuth2AuthenticationDetails) SecurityContextHolder.getContext().getAuthentication().getDetails()).getDecodedDetails();

是否有更干净的解决方案来使用JwtAccessTokenConverter但仍然能够将主体设置为自定义用户详细信息,而不是将其设置为(无用的)用户名并发送附加信息作为身份验证对象的详细信息?

共有1个答案

令狐阳秋
2023-03-14

我不能说这是否是首选的解决方案,但在我自己尝试解决同样的问题后,我最终扩展了DefaultUserAuthenticationConverter。

所以你可以这样做

@Bean
public JwtAccessTokenConverter accessTokenConverter() {
  DefaultAccessTokenConverter defaultConverter = new DefaultAccessTokenConverter();
  defaultConverter.setUserTokenConverter(new CustomUserAuthenticationConverter());

  JwtAccessTokenConverter jwtConverter = new JwtAccessTokenConverter();
  converter.setAccessTokenConverter(defaultConverter);
  return converter;
}

那么DefaultUserAuthenticationConverter不是很好扩展,因为大多数方法和属性都是私有的。但这里有一个例子

public class CustomUserAuthenticationConverter extends DefaultUserAuthenticationConverter {

  private static final String CUST_PROP = "custProp";

  @Override
  public Authentication extractAuthentication(Map<String, ?> map) {
    if (map.containsKey(USERNAME) && map.containsKey(CUST_PROP)) {
      String username = (String) map.get(USERNAME);
      String custProp = (String) map.get(CUST_PROP);

      CustomPrincipal principal = new CustomPrincipal();
      pricipal.setUsername(username);
      pricipal.setCustomProp(custProp);

      Collection<? extends GrantedAuthority> authorities = getAuthorities(map);
      return new UsernamePasswordAuthenticationToken(user, "N/A", authorities);
    }
    return null;
  }

  private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
    //Copy this method from DefaultUserAuthenticationConverter or create your own.
  }

}
 类似资料:
  • 问题内容: 我在同一包中有2个班级。这两个类都具有main方法。现在,我想构建一个jar文件。我想建立2个jar文件,这些文件使用不同的主要功能作为默认主要功能。 例如 如何在NetBeans IDE中进行操作? 我找到了答案。您可以在netbeans中轻松地做到这一点:1)右键单击项目>属性>运行>选择类frm并下拉列表。在netbeans中是如此简单。Netbeans摇摇欲坠! 问题答案: 在

  • 问题内容: 在我的文件中,具有以下内容。但是,容器不会选择主机名值。有任何想法吗? 当我检查容器中的主机名时,它没有启动。 问题答案: 我发现使用时主机名对其他容器不可见。事实证明这是一个已知问题(也许是一个已知功能),其中一部分讨论是: 我们可能应该在文档中添加有关使用主机名的警告。我认为它很少有用。 就容器网络而言,分配主机名的正确方法是定义一个别名,如下所示: 不幸的是,这 仍然 无法使用。

  • 在我的文件中,我有以下内容。但是容器没有选择主机名值。有什么想法吗? 当我检查容器中的主机名时,它不会拾取。

  • 我是库伯内特人。我在Minikube中配置的整个设置。我不确定它是否与其他kubernetes设置有所不同。 我已经在我的设置中创建了一个POD,一个Spring Boot应用程序正在8080端口上运行,这个服务将在20080端口上向集群公开。 我正在运行tcpDum的集群内运行另一个pod。我需要在20080上转储撞击集群的HTTP数据包。请告诉我如何从tcpDumpod访问集群接口。 我尝试了

  • /** 设置主题色(默认主题色是:#0684ea) @param themeColor 十六机制颜色 */ [Ntalker ntalker_themeColor:@"#0684ea"];

  • 我正在尝试在云中设置Jmeter的主从设置。 我在CLOUD中为主服务器和从服务器做的设置 我在Master中创建了文件,并将其复制到Slave机器上。 我在两台机器上都安装了相同版本的Java和Jeter 我在Master的文件中添加了Slave机器的IP地址 请帮助我,为什么当我试图在云机器中执行jmeter脚本时,会遇到连接超时错误。接收: 拒绝连接到主机:10。XXX . xx . XXX