您可以實施自己的自定義AuthenticationManager和自定義UsernamePasswordAuthenticationFilter。這是簡單的例子,但它可以給你一個想法,還爲您的信息,這是安全上下文:)非常敏感的部分
只需創建豆你spring_security.xml:
<http entry-point-ref="authenticationProcessingFilterEntryPoint"
use-expressions="true">
<custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" />
<custom-filter ref="customUsernamePasswordAuthenticationFilter"
position="FORM_LOGIN_FILTER" />
<session-management
session-authentication-strategy-ref="sas"></session-management>
</http>
<beans:bean id="authenticationProcessingFilterEntryPoint"
class="org.springframework.security.web.authentication.AuthenticationProcessingFilterEntryPoint">
<beans:property name="loginFormUrl" value="/login" />
</beans:bean>
<beans:bean id="sas"
class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy" />
<beans:bean id="customAuthenticationManager"
class="my.package.security.CustomAuthenticationManager" />
<beans:bean id="customUsernamePasswordAuthenticationFilter"
class="my.package.security.CustomUsernamePasswordAuthenticationFilter">
<beans:property name="sessionAuthenticationStrategy"
ref="sas" />
<beans:property name="authenticationManager" ref="customAuthenticationManager" />
<beans:property name="authenticationSuccessHandler">
<beans:bean
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<beans:property name="defaultTargetUrl" value="/main.xhtml" />
</beans:bean>
</beans:property>
<beans:property name="authenticationFailureHandler">
<beans:bean
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<beans:property name="defaultFailureUrl" value="/login.xhtml" />
</beans:bean>
</beans:property>
</beans:bean>
<beans:bean id="sessionManagementFilter"
class="org.springframework.security.web.session.SessionManagementFilter">
<beans:constructor-arg name="securityContextRepository"
ref="httpSessionSecurityContextRepository" />
</beans:bean>
<beans:bean id="httpSessionSecurityContextRepository"
class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />
當你實現CustomUsernamePasswordAuthenticationFilter覆蓋驗證並添加您的外部邏輯:
public final class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
CustomAuthentication auth = new CustomAuthentication();
// set details of current user
auth.setDetails(new WebAuthenticationDetails(request));
auth.setAuthenticated(true);
auth.setUserName(username);
// set authentication to current security session
LOGGER.info("Setting authentication into existing security context");
SecurityContextHolder.getContext().setAuthentication(auth);
// if validation done return generated authentication
return auth;
}
}
然後生成驗證對象將由認證管理器進行處理:
public final class CustomAuthenticationManager implements AuthenticationManager {
/*
* (non-Javadoc)
*
* @see org.springframework.security.authentication.AuthenticationManager#
* authenticate(org.springframework.security.core.Authentication)
*/
private static final Logger LOGGER = LoggerFactory.getLogger(CustomUsernamePasswordAuthenticationFilter.class);
private final BadCredentialsException badCredentialsException = new BadCredentialsException("Invalid username/password");
@Override
public Authentication authenticate(Authentication authentication) {
//check if user has valid authentication
if (authentication == null) {
LOGGER.debug("Null authentication");
throw badCredentialsException;
}
//Check mandatory fields
if (!Validator.isValidString((String) authentication.getPrincipal()) || !Validator.isValidString((String) authentication.getCredentials())) {
LOGGER.debug("Null/blank username/credential");
throw badCredentialsException;
}
//Check if there is any role assigned into user
if (authentication.getAuthorities() != null && authentication.getAuthorities().size() < 1) {
LOGGER.debug("No authority found");
throw badCredentialsException;
}
//Validate role
//IF ROLE VALIDATION REQUIRED YOU CAN HANDLE IT HERE
boolean authorityValid = false;
LOGGER.info("Validating user authentication. Total grantedAuth size: " + authentication.getAuthorities().size());
for (GrantedAuthority g : authentication.getAuthorities()) {
if (!authorityValid) {
//Testing purpose one type role available, when exact roles prepared create enum types
authorityValid = g.getAuthority().equals("ROLE_LDAP_AUTHENTICATED");
}
}
//if none of role matching to required throw exception
if(!authorityValid){
LOGGER.debug("User has authority but none of them matching");
throw badCredentialsException;
}
LOGGER.info("Final validation done returning authentication");
return authentication;
}
}
然後如果需要的話,您可以覆蓋默認的驗證對象也一樣,如果這裏位於動態角色是你處理:
public final class CustomAuthentication implements Authentication {
/**
*
*/
private static final long serialVersionUID = 1L;
private transient String userName;
private transient boolean authenticated;
private transient Object details;
private static final transient String ROLE = "ROLE_LDAP_AUTHENTICATED";
/*
* (non-Javadoc)
*
* @see java.security.Principal#getName()
*/
@Override
public String getName() {
return this.userName; //for dynamic username logic here
}
//IF ROLES DYNAMICALLY ALLOCATED ASSIGN IT HERE, HERE IS WHERE YOU READ FROM INTERCEPT URL
/*
* (non-Javadoc)
*
* @see org.springframework.security.core.Authentication#getAuthorities()
*/
@Override
public Collection<GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
auths.add(new GrantedAuthority() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public String getAuthority() {
if (authenticated) {
return ROLE;
}
return null;
}
});
return auths;
}
/*
* (non-Javadoc)
*
* @see org.springframework.security.core.Authentication#getCredentials()
*/
@Override
public Object getCredentials() {
//TODO: a specific algorithm can be stored
return userName + " is ldap authenticated user";
}
/*
* (non-Javadoc)
*
* @see org.springframework.security.core.Authentication#getDetails()
*/
@Override
public Object getDetails() {
return this.details;
}
/*
* (non-Javadoc)
*
* @see org.springframework.security.core.Authentication#getPrincipal()
*/
@Override
public Object getPrincipal() {
return userName;
}
/*
* (non-Javadoc)
*
* @see org.springframework.security.core.Authentication#isAuthenticated()
*/
@Override
public boolean isAuthenticated() {
return this.authenticated;
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.security.core.Authentication#setAuthenticated(boolean
*)
*/
@Override
public void setAuthenticated(boolean arg0) {
this.authenticated = arg0;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setDetails(Object details) {
this.details = details;
}
}
請你給我們你想如何給你的用戶進行身份驗證的詳細信息?您可以爲每個用戶隱式設置身份驗證令牌,但我不知道這是否是您想要的。外部應用程序提供什麼? –
我已經試過這段代碼:List authorities = new ArrayList (); authorities.add(new GrantedAuthorityImpl(「u」)); \t UsernamePasswordAuthenticationToken tok = new UsernamePasswordAuthenticationToken(「username」,「password」,authorities); \t SecurityContextHolder.getContext()。setAuthentication(tok);用戶名,密碼和角色的值來自外部應用程序。 –
Tostis
您可以嘗試像這樣將SecurityContext添加到會話中。 final HttpSession session = request.getSession(true); session.setAttribute(「SPRING_SECURITY_CONTEXT」,context);使SecurityContextPersistenceFilter知道上下文 –