Hello,
I've tried what's listed in topic http://forum.springframework.org/viewtopic.php?t=899, but I'm not having any success. Here is my problem:
A user in the application may be assigned many different roles such as ROLE_PROJECTA_ADMIN, ROLE_PROJECTB_ADMIN, ROLE_PROJECTB_WRITER, etc. I am using the Authorize Taglib to display content based on roles. So one could have the following scenerio. A user logs into the system and selects PROJECTA (User should only see PROJECTA related information). If the user is assigned roles ROLE_PROJECTA_ADMIN and ROLE_PROJECTB_WRITER, the user will see the link below regardless of the project she chooses:
Code:
<authz:authorize ifAllGranted="ROLE_PROJECTA_ADMIN, ROLE_PROJECTB_ADMIN">
<html:link action="/page""></html:link>
</authz:authorize>
The solution I attempted is as follows
1) User logs into the system. This is handled by a Struts controller that simply verifies the username and password and gathers the projects the user has access to.
2) The user is presented with a screen to choose the project she wants to work with. The username and passwords are stored as hidden fields.
3) Once the user selects the project, she is re-authenticated using the Acegi AuthenticationProcessingFilter. The AUTHORITIES table will has the columns (AUTHORITY,USERNAME,PROJECT_ID). I should be able to only retrieve authorities for that user based on the project and username. Something like the following:
Code:
SELECT USERNAME,AUTHORITY FROM AUTHORITIES A, WHERE USERNAME = ? AND PROJECT_ID = ?
Is there a better way to do this????
Following the advice from topic 899, I've extended the AuthenticationProcessingFilter and DaoAuthenticationProvider and added UsernamePasswordProjectAuthenticationToken. Is there something that
My AuthenticationProcessingFilter
Code:
package gmbpcm.security;
import net.sf.acegisecurity.Authentication;
import net.sf.acegisecurity.AuthenticationException;
import gmbpcm.security.UsernamePasswordProjectAuthenticationToken;
import net.sf.acegisecurity.providers.*;
import net.sf.acegisecurity.ui.*;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
public class AuthenticationProcessingFilter extends net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter {
//~ Static fields/initializers =============================================
public static final String ACEGI_SECURITY_FORM_USERNAME_KEY = "j_username";
public static final String ACEGI_SECURITY_FORM_PASSWORD_KEY = "j_password";
public static final String BOB_PROJECT_TYPE_KEY = "j_projecttype";
public static final String ACEGI_SECURITY_LAST_USERNAME_KEY = "ACEGI_SECURITY_LAST_USERNAME";
//~ Methods ================================================================
/**
* This filter by default responds to <code>/j_acegi_security_check</code>.
*
* @return the default
*/
public String getDefaultFilterProcessesUrl() {
return "/j_acegi_security_check";
}
public Authentication attemptAuthentication(HttpServletRequest request)
throws AuthenticationException {
String username = request.getParameter(ACEGI_SECURITY_FORM_USERNAME_KEY);
String password = request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY);
String projecttype = request.getParameter(BOB_PROJECT_TYPE_KEY);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
if (projecttype == null) {
projecttype = "";
}
UsernamePasswordProjectAuthenticationToken authRequest = new UsernamePasswordProjectAuthenticationToken(username,
password, projecttype);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
// Place the last username attempted into HttpSession for views
request.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY,
username);
return this.getAuthenticationManager().authenticate(authRequest);
}
public void init(FilterConfig filterConfig) throws ServletException {}
protected void setDetails(HttpServletRequest request,
UsernamePasswordProjectAuthenticationToken authRequest) {
authRequest.setDetails(request.getRemoteAddr());
}
}
My UsernamePasswordProjectAuthenticationToken
Code:
package gmbpcm.security;
import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.providers.*;
public class UsernamePasswordProjectAuthenticationToken
extends AbstractAuthenticationToken {
//~ Instance fields ========================================================
private Object credentials;
private Object details = null;
private Object principal;
private Object project;
private GrantedAuthority[] authorities;
private boolean authenticated = false;
//~ Constructors ===========================================================
public UsernamePasswordProjectAuthenticationToken(Object principal,
Object credentials, Object project) {
this.principal = principal;
this.credentials = credentials;
this.project = project;
}
public UsernamePasswordProjectAuthenticationToken(Object principal,
Object credentials, Object project, GrantedAuthority[] authorities) {
this.principal = principal;
this.credentials = credentials;
this.project = project;
this.authorities = authorities;
}
protected UsernamePasswordProjectAuthenticationToken() {
throw new IllegalArgumentException("Cannot use default constructor");
}
//~ Methods ================================================================
public void setAuthenticated(boolean isAuthenticated) {
this.authenticated = isAuthenticated;
}
public boolean isAuthenticated() {
return this.authenticated;
}
public void setAuthorities(GrantedAuthority[] authorities) {
this.authorities = authorities;
}
public GrantedAuthority[] getAuthorities() {
return this.authorities;
}
public Object getCredentials() {
return this.credentials;
}
public void setDetails(Object details) {
this.details = details;
}
public Object getDetails() {
return details;
}
public Object getPrincipal() {
return this.principal;
}
public Object getProject() {
return this.project;
}
}
You stated that I should subclass DaoAuthenticationProvider. This where I'm lost. What needs to happen in the isPasswordCorrect and createSuccessAuthentication methods. Do I need to subclass any other classes? Any help you can provide will be greatly appreciated.
Thanks,
Damon Henry