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

Spring security在登录失败时返回String作为主体而不是UserDetails?

景令秋
2023-03-14

或者我遗漏了一些东西,或者这就是它的工作原理…
也就是说,我实现了UserDetailsService,并子类(AppUser)spring实用程序类User,实现了UserDetails)。如果有关系,它是这样的:

@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
    // try loading user by its name
    SystemUser user = null;
    try {
        user = this.sysUserService.getByUsername(username);
        if(user == null)
            throw new UsernameNotFoundException("User not found!");
    }
    catch(Exception e) {
        throw new DataRetrievalFailureException(
                "Could not load user with username: " + username);
    }
    // load user rights, and create UserDetails instance
    UserDetails res = new AppUser(user, getUserAuthorities(user));

    return res;
}

然后,我尝试使用以下方法实现帐户锁定:

public class LoginFailureEventListenter implements
ApplicationListener<AuthenticationFailureBadCredentialsEvent> {

// rest omitted for brevity

@Override
public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) {
    // ...

    SystemUser user = ((AppUser)event.getAuthentication().getPrincipal()).getSystemUser();
    // cast exception - how is it possible to obtain String 
    // instead of UserDetails object here ?
    // ...
}
}

但是,在试图从提供的事件参数中获取主体对象时,我遇到了java.lang.ClassCastException(主体对象的类型为String)。我的意思是,好的--我可以再次按用户名加载我的SystemUser,以解决这个问题,但我没有料到会出现这种情况。...
我认为,对于这个场景,即使是源代码文档也声明getPrincipal()应该返回UserDetails实例。
有什么想法?

共有1个答案

滕弘新
2023-03-14

由于我们正在处理身份验证失败,因此事件中的authentication对象是提交给AuthenticationManager(但被拒绝)的对象。

在典型的场景中,这将是UsernamePasswordAuthenticationToken,其中“principal”属性是提交的用户名。

AuthenticationManager支持许多不同的身份验证机制,从它的角度来看,不能保证身份验证涉及UserDetailsService。它只知道身份验证令牌没有被接受(有一个异常),并相应地发布事件。

替代选项是自定义正在使用的AuthenticationProvider或插入AuthenticationFailureHandler(例如,如果使用表单登录)并在其中执行额外的工作。

 类似资料:
  • 代码段用于获取从文本文件中提取的一行文本,将其分离为单独的标记,并将每个标记存储在数组的索引中。起初我以为问题出在文本文件上,但是直接将字符串放入编辑器并不能解决这个问题。 使用字符串,如: 带分隔符的StringTokenizer对象返回前四个标记作为正确的字符串,但其余四个标记为null。 有趣的是,另一个字符串: “Gnollnonegeralany222taunttaunt” 鸡肉没有野兽

  • 我想用第二个前端应用程序扩展jHipster的整体设置,该应用程序从不同的URL访问相同的API。作为第一步,我已经在中启用了CORS,并使用标志从前端发送请求。我使用的是会话,而不是JWT身份验证。 现在许多方法都能按预期工作,但不是所有方法都能工作。飞行前(请求)总是按照预期进行并工作。此呼叫的响应包含正确的CORS头。 我在想,我在这里做错了什么。我猜标题设置得不对。我现在可以手动添加头(例

  • 我正在尝试以下方法,并认为我会失败 但是我却得到了 有人能回答为什么吗?

  • 我寻找如何在堆栈溢出的Java中进行IP查找,但答案与我已经在做的匹配,并没有解决我的问题。 问题:此代码与预期的一些IP广告,而不是与其他一些。 例如,对于IP 157.55.39.29,输出为: 根据Linux命令,此结果似乎是正确的: 返回: 此IP地址的完全限定域名,如果安全检查不允许此操作,则返回IP地址的文本表示形式。 但我很确定这不是安全检查的问题...或者我不明白出了什么问题。 你

  • 这是一个概念问题。 我这样问的原因是,有些其他RESTful服务使用401处理错误的凭据,即使您只是询问凭据是否有效。然而,我对401响应的理解是,它们代表了一个没有有效凭据的资源。但登录资源应该对任何人都可以访问,因为登录资源的全部目的是告诉您凭据是否有效。 换句话说,在我看来,像这样的请求: 如果提供了错误的凭据,则应返回401。而是这样的请求: 关于这件事,我想听听一些合理的意见。处理这件事

  • 我试图理解map和flatMap是如何工作的,但是在下面的代码中被卡住了。flatMap()函数返回一个RDD[Char],但我希望返回的是RDD[String]。有人能解释为什么它会产生RDD[Char]吗?