Spring Security-用户身份验证有时会失败,并且用户将被重定向到登录页面

多尔菲兹

我的环境:

  • Java 6
  • Servlet 2.5
  • Weblogic 12.1
  • Spring MVC 4.3.4。发布
  • Spring Security 4.2.0。发布

我已经实现了CustomAuthenticationProvider以便根据Oracle数据库验证用户身份:用户实际上是数据库用户,因此我尝试连接到数据库以检查用户/密码,并且结果是否比我加载权限大。

除登录错误后外,配置工作正常。如果用户键入错误的用户名或密码,则应用程序将在同一页面上显示错误消息,但是进一步的正确尝试不会使用户登录。而是重定向到登录页面。如果用户再次尝试,则问题仍然存在。一分钟后,无需重新加载页面即可进行相同的尝试。

就像我说的那样,仅在登录错误之后才出现此问题如果用户在第一次尝试或注销后正确键入了自己的凭据,则不会发生任何问题。如果他在登录错误后执行此操作,则问题将出现。另外,在我的开发环境(本地应用服务器和各种浏览器)上没有发生任何错误,但是问题在每次升级环境(相同的应用服务器但集中式和IE9-IE10-Edge)上每次都会出现我真的不明白是什么与众不同。

我在CustomAuthenticationProvider上放了很多日志,可以看到在两种情况下(正向和负向登录)用户名和密码均已成功接受,并且创建UsernamePasswordAuthenticationToken然后,应该将用户重定向到默认目标URL,即我的应用程序根目录/(我将always-use-default-target = true设置为true)。由于我不明白的原因,当问题发生时,重定向失败,因为Spring Security认为用户尚未获得访问安全路径的权限,因此会再次将其重定向到登录页面。

我已经用两种形式的登录表单提交检查了请求,除了传递的JSESSIONID之外,它们实际上是相同的。但是登录成功,我可以从响应标头中看到已设置JSESSIONID cookie,在否定的情况下,则没有“ set cookie”。

尽管提交的用户名和密码相同,但为什么会有这种行为上的差异呢?有什么可以改变的?我的猜测是错误的登录尝试会留下一些肮脏的东西。有一些影响下一次尝试。会是什么呢?为什么只在我的本地环境中出现此问题?我想念什么?

这是CustomAuthenticationProvider的实现

@Component
public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

private Logger log = LogManager.getLogger(CustomAuthenticationProvider.class);

@Autowired
private UserService userService;

@Autowired
private SecurityService securityService;

@Autowired
private Messages messages;

@Value("${login.test.mode}")
private String testMode;

@Value("${login.test.mode.userid}")
private String testModeUserid;

public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    String username = authentication.getName();
    String password = (String) authentication.getCredentials();

    log.debug("##### SECURITY ##### Test mode status: " + testMode);

    // test mode uses its own configured user, ignoring login credentials, if username is empty
    if (Constants.FLAG_YES.equals(testMode) && StringUtils.isEmpty(username)) {
        username = testModeUserid;
    }

    GddbUserDetails gddbUserDetails = userService.findGddbUserDetailsByUsername(username);
    UserRole userRole = userService.findUserRolesByUsername(username);

    if (gddbUserDetails == null) {
        log.debug("##### SECURITY ##### Utente non trovato in anagrafica GDDB: " + username);
        throw new BadCredentialsException(messages.get("user.not.found.gddb"));
    } else {
        log.debug("##### SECURITY ##### OK Utente trovato in anagrafica GDDB: " + username);
    }

    // perform checks only if test mode is disabled
    if (!Constants.FLAG_YES.equals(testMode)) {
        // GDDB state check
        if (!Constants.USER_STATO_ACTIVE.equals(gddbUserDetails.getStato())) {
            log.debug("##### SECURITY ##### Utente presente in anagrafica GDDB ma disabilitato: " + username);
            throw new BadCredentialsException(messages.get("user.not.enabled.gddb"));
        } else {
            log.debug("##### SECURITY ##### Utente presente in anagrafica GDDB e abilitato: " + username);
        }
        // dbetichette user existence check
        if (userRole == null) {
            log.debug("##### SECURITY ##### Utente non presente in anagrafica DBEtichette: " + username);
            throw new BadCredentialsException(messages.get("user.not.enabled.locally"));
        } else {
            log.debug("##### SECURITY ##### Utente presente in anagrafica DBEtichette: " + username);
        }
        // dbetichette user activation check
        if (!Constants.FLAG_YES.equals(userRole.getActive())) {
            log.debug("##### SECURITY ##### Utente disabilitato in anagrafica DBEtichette: " + username);
            throw new BadCredentialsException(messages.get("user.not.enabled.locally"));
        } else {
            log.debug("##### SECURITY ##### Utente abilitato in anagrafica DBEtichette: " + username);
        }

        // oracle user password check
        String usernamePasswordCheckResult = securityService.checkUserPassword(username, password);
        log.debug("##### SECURITY ##### usernamePasswordCheckResult: " + usernamePasswordCheckResult);

        if (Constants.SECURITY_ACCOUNT_LOCKED.equals(usernamePasswordCheckResult)) {
            log.debug("##### SECURITY ##### Utente presente su DB ma bloccato: " + username);
            throw new BadCredentialsException(messages.get("user.blocked"));
        } else if (Constants.SECURITY_PASSWORD_EXPIRED.equals(usernamePasswordCheckResult)) {
            log.debug("##### SECURITY ##### Password dell'utente scaduta: " + username);
            throw new BadCredentialsException(messages.get("user.password.expired"));
        } else if (Constants.SECURITY_INVALID_USERNAME_PASSWORD.equals(usernamePasswordCheckResult)) {
            log.debug("##### SECURITY ##### Tentativo di accesso fallito per errata password: " + username);
            throw new BadCredentialsException(messages.get("user.password.wrong"));
        } else if (!Constants.SECURITY_VALID_USERNAME_PASSWORD.equals(usernamePasswordCheckResult)) {
            log.debug("##### SECURITY ##### Tentativo di accesso fallito per motivo sconosciuto: " + username
                    + " ( usernamePasswordCheckResult = " + usernamePasswordCheckResult + " )");
            throw new BadCredentialsException(messages.get("user.login.error.other"));
        } else {
            log.debug("##### SECURITY ##### Tentativo di accesso eseguito con successo: " + usernamePasswordCheckResult + " - " + username);
        }

    }

    CustomUser user = userService.createCustomUser(gddbUserDetails, userRole);
    log.debug("##### SECURITY ##### Creazione custom user: " + user);

    Collection<? extends GrantedAuthority> authorities = user.getAuthorities();

    UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken(user, password, authorities);
    log.debug("##### SECURITY ##### Creazione userToken: " + userToken);

    return userToken;

}

@Override
protected UserDetails retrieveUser(String s, UsernamePasswordAuthenticationToken token) throws AuthenticationException {

    UserDetails user = (UserDetails) token.getPrincipal();
    log.debug("##### SECURITY ##### retrieveUser: " + user);
    return user;
}

@Override
public boolean supports(Class<?> aClass) {
    return true;
}

@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken token) throws AuthenticationException {
    log.debug("##### SECURITY ##### additionalAuthenticationChecks - userDetails " + userDetails);
    log.debug("##### SECURITY ##### additionalAuthenticationChecks - token " + token);
}

}

这是我的Spring Security配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://www.springframework.org/schema/security"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
                            http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/security
                            http://www.springframework.org/schema/security/spring-security.xsd">

<http auto-config="true">
    <intercept-url pattern="/assets/**" access="permitAll()"/>
    <intercept-url pattern="/pages/**" access="permitAll()"/>
    <intercept-url pattern="/login" access="permitAll()"/>
    <intercept-url pattern="/loginApp" access="permitAll()"/>
    <intercept-url pattern="/loginFailed" access="permitAll()"/>
    <intercept-url pattern="/logout" access="permitAll()"/>
    <intercept-url pattern="/logoutSuccess" access="permitAll()"/>
    <intercept-url pattern="/changepwd" access="permitAll()"/>
    <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
    <intercept-url pattern="/relabel/**" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_WAREHOUSE_OP') or hasRole('ROLE_QA')"/>
    <intercept-url pattern="/**" access="hasRole('ROLE_DATA_ENTRY') or hasRole('ROLE_APPROVER') or hasRole('VIEWER') or hasRole('ROLE_ADMIN') or hasRole('ROLE_WAREHOUSE_OP') or hasRole('ROLE_QA')"/>
    <form-login login-page="/login"
                default-target-url="/"
                authentication-failure-url="/loginFailed"
                login-processing-url="/loginApp"
                username-parameter="username"
                password-parameter="password"
                always-use-default-target="true"
    />
    <logout logout-success-url="/logoutSuccess" logout-url="/logout"/>
    <access-denied-handler error-page="/403"/>

    <csrf disabled="true" />
</http>

<authentication-manager>
    <authentication-provider ref="customAuthenticationProvider"/>
</authentication-manager>

每个建议都表示赞赏。谢谢大家,多尔菲兹

编辑:我使spring安全日志工作,并且似乎由于某种原因,身份验证后会话已被清除,因此转发到登录页面。这些是日志:

[DEBUG] 2017-02-17 17:01:41.317 org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@e2fe4b0e: Principal: CustomUser{username='MAROTAN1', password='null', email='[email protected]', firstName='Antonio', lastName='Marotta', graceTime='null', authorities=[Role{name='ROLE_ADMIN'}], accountNonExpired=true, accountNonLocked=true, credentialsNonExpired=true, enabled=true}; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 10.166.243.87; SessionId: QYWPYnpbth0y139v2gz7r6hCm0cHpsfmxq8DFqsvv3XM1kT6YcP2!2062762872!1487347291632; Granted Authorities: Role{name='ROLE_ADMIN'}
[DEBUG] 2017-02-17 17:01:41.317 org.springframework.security.web.DefaultRedirectStrategy - Redirecting to '/dbetichette/'
[DEBUG] 2017-02-17 17:01:41.317 org.springframework.security.web.context.HttpSessionSecurityContextRepository - HttpSession is now null, but was not null at start of request; session was invalidated, so do not create a new session
[DEBUG] 2017-02-17 17:01:41.317 org.springframework.security.web.context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
[DEBUG] 2017-02-17 17:01:41.321 org.springframework.security.web.FilterChainProxy - / at position 1 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
[DEBUG] 2017-02-17 17:01:41.321 org.springframework.security.web.context.HttpSessionSecurityContextRepository - No HttpSession currently exists
[DEBUG] 2017-02-17 17:01:41.322 org.springframework.security.web.context.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
[DEBUG] 2017-02-17 17:01:41.322 org.springframework.security.web.FilterChainProxy - / at position 2 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
[DEBUG] 2017-02-17 17:01:41.322 org.springframework.security.web.FilterChainProxy - / at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
[DEBUG] 2017-02-17 17:01:41.323 org.springframework.security.web.FilterChainProxy - / at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
[DEBUG] 2017-02-17 17:01:41.323 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/logout'
[DEBUG] 2017-02-17 17:01:41.323 org.springframework.security.web.FilterChainProxy - / at position 5 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
[DEBUG] 2017-02-17 17:01:41.323 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Request 'GET /' doesn't match 'POST /loginApp
[DEBUG] 2017-02-17 17:01:41.323 org.springframework.security.web.FilterChainProxy - / at position 6 of 12 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
[DEBUG] 2017-02-17 17:01:41.324 org.springframework.security.web.FilterChainProxy - / at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
[DEBUG] 2017-02-17 17:01:41.324 org.springframework.security.web.FilterChainProxy - / at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
[DEBUG] 2017-02-17 17:01:41.324 org.springframework.security.web.FilterChainProxy - / at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
[DEBUG] 2017-02-17 17:01:41.324 org.springframework.security.web.authentication.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@6faa3d44: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 10.166.243.87; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
[DEBUG] 2017-02-17 17:01:41.325 org.springframework.security.web.FilterChainProxy - / at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
[DEBUG] 2017-02-17 17:01:41.325 org.springframework.security.web.session.SessionManagementFilter - Requested session ID QYWPYnpbth0y139v2gz7r6hCm0cHpsfmxq8DFqsvv3XM1kT6YcP2!2062762872 is invalid.
[DEBUG] 2017-02-17 17:01:41.325 org.springframework.security.web.FilterChainProxy - / at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
[DEBUG] 2017-02-17 17:01:41.325 org.springframework.security.web.FilterChainProxy - / at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
[DEBUG] 2017-02-17 17:01:41.325 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/assets/**'
[DEBUG] 2017-02-17 17:01:41.325 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/pages/**'
[DEBUG] 2017-02-17 17:01:41.326 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/login'
[DEBUG] 2017-02-17 17:01:41.326 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/loginApp'
[DEBUG] 2017-02-17 17:01:41.326 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/loginFailed'
[DEBUG] 2017-02-17 17:01:41.326 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/logout'
[DEBUG] 2017-02-17 17:01:41.326 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/logoutSuccess'
[DEBUG] 2017-02-17 17:01:41.326 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/changepwd'
[DEBUG] 2017-02-17 17:01:41.327 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/admin/**'
[DEBUG] 2017-02-17 17:01:41.327 org.springframework.security.web.util.matcher.AntPathRequestMatcher - Checking match of request : '/'; against '/relabel/**'
[DEBUG] 2017-02-17 17:01:41.327 org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /; Attributes: [hasRole('ROLE_DATA_ENTRY') or hasRole('ROLE_APPROVER') or hasRole('VIEWER') or hasRole('ROLE_ADMIN') or hasRole('ROLE_WAREHOUSE_OP') or hasRole('ROLE_QA')]
[DEBUG] 2017-02-17 17:01:41.327 org.springframework.security.web.access.intercept.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@6faa3d44: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffff4c9c: RemoteIpAddress: 10.166.243.87; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
[DEBUG] 2017-02-17 17:01:41.328 org.springframework.security.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@14b4feab, returned: -1
[DEBUG] 2017-02-17 17:01:41.329 org.springframework.security.web.access.ExceptionTranslationFilter - Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied

我想重要的一行是:

[DEBUG] 2017-02-17 17:01:41.317 org.springframework.security.web.context.HttpSessionSecurityContextRepository - HttpSession is now null, but was not null at start of request; session was invalidated, so do not create a new session

为什么仅在某些环境下才发生这种情况?

多尔菲兹

在这里这里阅读针对不同但相似问题的解决方案时,我猜想我的也是一个并发问题,与会话管理有关。

因此,我尝试在securityConfig.xml会话管理中设置显式配置,将每个用户允许的身份验证会话数限制为1:

<session-management session-fixation-protection="newSession">
    <concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
</session-management>

并将所需的侦听器放在my上web.xml

<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

这些变化完全解决了问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

成功通过身份验证后,通过提供拒绝访问的异常,Spring Security重定向到登录页面

来自分类Dev

Spring Security Lgoin始终重定向到身份验证失败URL

来自分类Dev

如果用户未经授权,Spring Security如何重定向到“登录”页面

来自分类Dev

使用Spring Security登录后无法将用户重定向到所需页面

来自分类Dev

登录后,Spring Security再次重定向到登录页面

来自分类Dev

Spring Security:登录后重定向到登录页面

来自分类Dev

Spring Security:登录后重定向到登录页面

来自分类Dev

登录后,Spring Security再次重定向到登录页面

来自分类Dev

如果在java spring security 中登录身份验证失败,如何获取anonymousUser 用户名?

来自分类Dev

身份验证失败的Spring Security Wildfly

来自分类Dev

当他尝试进入登录页面时,使用 java spring-security 重定向已经登录的用户

来自分类Dev

Spring Security总是重定向到登录页面

来自分类Dev

Spring Security和angular javascript重定向到登录页面

来自分类Dev

Spring Security和Angular javascript重定向到登录页面

来自分类Dev

Spring Security:根据某些条件重定向登录的用户

来自分类Dev

我想首先查看登录页面,即使任何用户想要访问其他页面也需要在Spring Security中重定向到登录页面

来自分类Dev

Spring Security无法验证用户

来自分类Dev

Spring Security用户信息

来自分类Dev

具有角色的经过身份验证的用户的Spring Security Java配置

来自分类Dev

如何在Spring Security身份验证登录中让用户输入用户名和密码的值

来自分类Dev

如何在Spring Security身份验证登录中让用户输入用户名和密码的值

来自分类Dev

Spring Security-基于令牌的API身份验证和用户/密码身份验证

来自分类Dev

Spring Security将自定义登录页面重定向到其自身-重定向过多

来自分类Dev

使用重定向:uri登录后将Spring Security重定向到页面

来自分类Dev

从Spring Security中排除从登录页面重定向的特定页面

来自分类Dev

Angular与Spring Security登录和身份验证

来自分类Dev

使用 JHipster、Spring Security 和 oauth2 控制身份验证重定向

来自分类Dev

Spring Security无法登录

来自分类Dev

Spring Security登录表单

Related 相关文章

  1. 1

    成功通过身份验证后,通过提供拒绝访问的异常,Spring Security重定向到登录页面

  2. 2

    Spring Security Lgoin始终重定向到身份验证失败URL

  3. 3

    如果用户未经授权,Spring Security如何重定向到“登录”页面

  4. 4

    使用Spring Security登录后无法将用户重定向到所需页面

  5. 5

    登录后,Spring Security再次重定向到登录页面

  6. 6

    Spring Security:登录后重定向到登录页面

  7. 7

    Spring Security:登录后重定向到登录页面

  8. 8

    登录后,Spring Security再次重定向到登录页面

  9. 9

    如果在java spring security 中登录身份验证失败,如何获取anonymousUser 用户名?

  10. 10

    身份验证失败的Spring Security Wildfly

  11. 11

    当他尝试进入登录页面时,使用 java spring-security 重定向已经登录的用户

  12. 12

    Spring Security总是重定向到登录页面

  13. 13

    Spring Security和angular javascript重定向到登录页面

  14. 14

    Spring Security和Angular javascript重定向到登录页面

  15. 15

    Spring Security:根据某些条件重定向登录的用户

  16. 16

    我想首先查看登录页面,即使任何用户想要访问其他页面也需要在Spring Security中重定向到登录页面

  17. 17

    Spring Security无法验证用户

  18. 18

    Spring Security用户信息

  19. 19

    具有角色的经过身份验证的用户的Spring Security Java配置

  20. 20

    如何在Spring Security身份验证登录中让用户输入用户名和密码的值

  21. 21

    如何在Spring Security身份验证登录中让用户输入用户名和密码的值

  22. 22

    Spring Security-基于令牌的API身份验证和用户/密码身份验证

  23. 23

    Spring Security将自定义登录页面重定向到其自身-重定向过多

  24. 24

    使用重定向:uri登录后将Spring Security重定向到页面

  25. 25

    从Spring Security中排除从登录页面重定向的特定页面

  26. 26

    Angular与Spring Security登录和身份验证

  27. 27

    使用 JHipster、Spring Security 和 oauth2 控制身份验证重定向

  28. 28

    Spring Security无法登录

  29. 29

    Spring Security登录表单

热门标签

归档