我的環境:的Spring Security - 用戶驗證有時會失敗,並且用戶將被重定向到登錄頁面
- 的Java 6
- 的Servlet 2.5
- 的Weblogic 12.1
- Spring MVC的4.3.4.RELEASE
- Spring Security 4.2.0.RELEASE
我已經實施了CustomAuthenticationProvider爲了根據Oracle數據庫對用戶進行身份驗證:用戶實際上是db用戶,因此我嘗試連接數據庫以檢查用戶/密碼,並且如果結果比我負載權限更好。
除登錄錯誤之外,配置工作正常。如果用戶輸入錯誤的用戶名或密碼,則應用程序會在同一頁面中顯示錯誤消息,但進一步正確的嘗試不會讓用戶登錄。而是被重定向到登錄頁面。如果用戶再次嘗試,則問題仍然存在。一分鐘後,同樣的嘗試,沒有頁面重新加載,是成功的。
正如我所說的,只有在登錄錯誤後纔會出現問題。如果用戶在第一次嘗試或註銷後正確輸入其憑據,則不會出現問題。如果他在登錄錯誤後執行此操作,則會出現問題。此外,無可厚非發生在我的開發環境(本地應用程序服務器和各種瀏覽器)但問題顯示出來,每次上分期environemnt(相同的應用程序服務器,但中央和IE9,IE10-EDGE)。我真的不明白是什麼造成了差異。
我把我的CustomAuthenticationProvider很多日誌,我可以比在兩種情況下(正面和負面的登錄)的用戶名和密碼已成功接受和UsernamePasswordAuthenticationToken已創建看到。然後,用戶應該被重定向到默認目標URL這是我的應用程序根目錄/(我設置總是使用默認的目標 = TRUE)。出於一個我不明白的原因,當問題發生時,重定向失敗,因爲Spring Security認爲用戶尚未獲得授權來訪問安全路徑,並將其重定向到登錄頁面。
我已經檢查了這兩種情況下的登錄表單提交請求,它們實際上是相同的,除了傳遞的JSESSIONID。但是,從響應頭中可以看到,登錄成功,JSESSIONID cookie已設置,否定情況下沒有「設置cookie」。
儘管事實上提交的用戶名和密碼是相同的,爲什麼會有這種差異?什麼可以有所作爲? 我的猜測是,一個錯誤的登錄嘗試留下了一些骯髒的東西。影響下次嘗試的東西。 Whan可以嗎?爲什麼這個問題只發生在我的本地環境中?我錯過了什麼?
這是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);
}
}
這是我的春季安全配置文件:
<?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>
每一個建議表示讚賞。 謝謝大家, dolfiz
編輯:我做了春季安全日誌工作,似乎出於某種原因會話已被認證後清除,因此前進到登錄頁面。 這些日誌:
[DEBUG] 2017-02-17 17:01:41.317 org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframew[email protected]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.sprin[email protected]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.sprin[email protected]6faa3d44: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]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.sprin[email protected]6faa3d44: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]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.sp[email protected]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
這究竟是爲什麼只是有時,只有在一些enviroments?
爲什麼-1?根據某人我的問題沒有顯示任何研究工作,或者可能不清楚和/或沒有用:/ – Dolfiz