Java 如何添加有关用户未通过身份验证的原因的详细信息?

Java 如何添加有关用户未通过身份验证的原因的详细信息?,java,spring,authentication,error-handling,spring-security,Java,Spring,Authentication,Error Handling,Spring Security,我们为用户添加了属性isBlocked 设置以下属性后,用户无法登录我们的网站 我们希望呈现错误消息“您的帐户被临时阻止…” 但我不知道如何将此消息传递给loginFailed控制器方法 我有以下spring安全配置: public class XXXSecurityServiceImpl implements UserDetailsService { @Autowired private TerminalAdminDao terminalAdminDao; @Ove

我们为用户添加了属性
isBlocked

设置以下属性后,用户无法登录我们的网站

我们希望呈现错误消息
“您的帐户被临时阻止…”

但我不知道如何将此消息传递给loginFailed控制器方法

我有以下spring安全配置:

public class XXXSecurityServiceImpl implements UserDetailsService {

    @Autowired
    private TerminalAdminDao terminalAdminDao;

    @Override
public UserDetails loadUserByUsername(String adminName) throws UsernameNotFoundException,
        DataAccessException {
    TerminalAdmin admin = terminalAdminDao.findAdminByEmail(adminName);
    UserDetails userDetails = null;
    if (admin != null) {
        Set<SimpleGrantedAuthority> authorities = new HashSet<SimpleGrantedAuthority>();
        for (AdminRole adminRole : admin.getAdminRoles()) {
            authorities.add(new SimpleGrantedAuthority(adminRole.getRole()));
        }
        userDetails = new User(admin.getEmail(), admin.getPassword(), true, true, true, !admin.isBlocked(),
                authorities);
    }
    return userDetails;
}

如何在控制器中理解用户被阻止?

基本上,您需要注册自定义身份验证提供程序和自定义身份验证失败处理程序来处理身份验证异常


检查这个问题。

基本上,您需要注册自定义身份验证提供程序和自定义身份验证失败处理程序来处理身份验证异常

检查这个问题。

这很有效

添加到控制器:

    @RequestMapping(value = "/loginAdminFailed", method = RequestMethod.GET)
    public String loginError(HttpSession session, HttpServletRequest request) {
        session.setAttribute("message", getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION"));
        return "admin/login";
    }
    // customize the error message
    private String getErrorMessage(HttpServletRequest request, String key) {
        Exception exception = (Exception) request.getSession().getAttribute(key);
        String error = "";
        if (exception instanceof BadCredentialsException) {
            error = messageSource.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.badCredentials", null, LOCALE_RU);
        } else if (exception instanceof LockedException) {
            error = messageSource.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.accountIsLocked", null, LOCALE_RU);
        } else {
            error = messageSource.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.badCredentials", null, LOCALE_RU);
        }

        return error;
    }
但这看起来很难看

这很管用

添加到控制器:

    @RequestMapping(value = "/loginAdminFailed", method = RequestMethod.GET)
    public String loginError(HttpSession session, HttpServletRequest request) {
        session.setAttribute("message", getErrorMessage(request, "SPRING_SECURITY_LAST_EXCEPTION"));
        return "admin/login";
    }
    // customize the error message
    private String getErrorMessage(HttpServletRequest request, String key) {
        Exception exception = (Exception) request.getSession().getAttribute(key);
        String error = "";
        if (exception instanceof BadCredentialsException) {
            error = messageSource.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.badCredentials", null, LOCALE_RU);
        } else if (exception instanceof LockedException) {
            error = messageSource.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.accountIsLocked", null, LOCALE_RU);
        } else {
            error = messageSource.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.badCredentials", null, LOCALE_RU);
        }

        return error;
    }


但这看起来很难看

从安全角度来看,通常附加消息是个坏主意。如果黑客收到该消息,它知道用户名有效(可能也是密码,因为不匹配使用了不同的消息)。其次,你是在错误的地方做的,这不是服务的任务。
AbstractUserDetailsAuthenticationProvider
已经做到了这一点,如果您只需设置
accountNonLocked
属性,而不是自行创建属性,则可以实现这一点。这样,您将获得一个
LockedException
,您可以为其添加一条自定义消息。@M.Deinum在当前实现密码中不是只检查登录名。黑客只能理解以下用户名存在,直到有额外的消息向黑客提供信息。@M.Deinum您能提供更多详细信息吗?通常从安全角度来看,额外的消息是个坏主意。如果黑客收到该消息,它知道用户名有效(可能也是密码,因为不匹配使用了不同的消息)。其次,你是在错误的地方做的,这不是服务的任务。
AbstractUserDetailsAuthenticationProvider
已经做到了这一点,如果您只需设置
accountNonLocked
属性,而不是自行创建属性,则可以实现这一点。这样,您将获得一个
LockedException
,您可以为其添加一条自定义消息。@M.Deinum在当前实现密码中不是只检查登录名。黑客只能理解以下用户名存在,直到有额外的消息向黑客提供信息。@M.Deinum您能提供更多详细信息吗?如何将数据从处理程序传递到控制器方法?为什么需要转到控制器,安全性高于控制器,登录失败处理程序或身份验证提供程序可以直接处理异常并将响应重定向到视图或直接在响应流中写入错误。如何将数据从处理程序传递到控制器方法?为什么需要转到控制器,安全性高于控制器,登录失败处理程序或身份验证提供程序可以直接处理异常并将响应重定向到视图或直接在响应流中写入错误。为什么?请参阅@M.Deinum您想说我不应该使用自定义消息源,而应该使用使用内部spring security的消息吗?我知道如何配置这个源代码,但我不知道如何获取这个消息并将其传递给jsp。您不需要Spring,它将为您处理这个问题。
AbstractUserDetailsAuthenticationProvider.accountIsLocked
用作查找实际消息的消息代码。只需在消息属性文件中放入类似于
AbstractUserDetailsAuthenticationProvider.accountIsLocked=User locked
的内容,它将被自动使用,您无需执行任何其他操作。@M.Deinum请澄清它将被自动使用的含义是什么?哪里?春天会处理好的。如果配置了
MessageSource
,它会将代码转换为消息。请阅读初始评论中提供的链接。基本上,你正在走向复杂。为什么?请参阅@M.Deinum您想说我不应该使用自定义消息源,而应该使用使用内部spring security的消息吗?我知道如何配置这个源代码,但我不知道如何获取这个消息并将其传递给jsp。您不需要Spring,它将为您处理这个问题。
AbstractUserDetailsAuthenticationProvider.accountIsLocked
用作查找实际消息的消息代码。只需在消息属性文件中放入类似于
AbstractUserDetailsAuthenticationProvider.accountIsLocked=User locked
的内容,它将被自动使用,您无需执行任何其他操作。@M.Deinum请澄清它将被自动使用的含义是什么?哪里?春天会处理好的。如果配置了
MessageSource
,它会将代码转换为消息。请阅读初始评论中提供的链接。基本上,你正在走向复杂。