Programmatically add roles after authentication

I have the following JSF 2.1 login form working in Glassfish 3.1

<h:form id="loginForm"> <h:panelGrid columns="2" cellspacing="5"> <h:outputText value="Username" /> <h:inputText value="#{loginHandler.username}" /> <h:outputText value="Password:" /> <h:inputText value="#{loginHandler.password}" /> <h:outputLabel value="" /> <h:commandButton value="Login" action="#{loginHandler.login}" /> </h:panelGrid> </h:form> 

And the next bean support.

 public String login() throws IOException, LoginException { log.debug("Trying to login with username " + username); HttpSession session = getRequest().getSession(true); try { getRequest().login(username, password); // if OK, add Roles ???????? ................... } catch (ServletException e) { // TODO Auto-generated catch block e.printStackTrace(); } log.debug("USER principal === " + getRequest().getUserPrincipal()); return "home"; } 

The question is, how can I add roles programmatically in UserPrincipal after a successful login?

Update 1: I tried to get the item using the following code, but subject == null.

 Subject thisSubject = Subject.getSubject(AccessController .getContext()); 

Thanks Cohen

+6
source share
2 answers

I came up with the following solution for adding roles programmatically after logging in, which works at least on GlassFish 3.1.2 build 23.

 import com.sun.enterprise.security.SecurityContext; import com.sun.enterprise.security.web.integration.PrincipalGroupFactory; import java.security.Principal; import java.util.Set; import javax.security.auth.Subject; import org.glassfish.security.common.Group; public class GlassFishUtils { public static void addGroupToCurrentUser(String groupName, String realmName) { Subject subject = SecurityContext.getCurrent().getSubject(); Set<Principal> principals = subject.getPrincipals(); Group group = PrincipalGroupFactory.getGroupInstance(groupName, realmName); if (!principals.contains(group)) principals.add(group); } } 

You will need to add security.jar and common-util.jar from GlassFish to your project libraries.

And don't forget to create the <security-role> section in your web.xml for the roles you want to add.

Please note that I am using functionality that does not appear to be part of the published stable API, so there is no guarantee that this will continue to work in future releases of GlassFish.

I got information on how to add roles from the source code of sun.appserv.security.AppservPasswordLoginModule.commit() GlassFish. If a future release of GlassFish breaks my code, this feature will be a good place to start to learn how to fix it.

+5
source

OK, I figured out a workaround that doesn't fit me 100%, but suggestions are welcome :)

 public void login() throws IOException, LoginException { log.debug("Trying to login with username " + username); try { getRequest().login(username, password); HttpSession session = getRequest().getSession(true); Subject subject = (Subject) session .getAttribute("javax.security.auth.subject"); if (subject == null) { log.debug("Subject is null, creating new one"); subject = new Subject(); subject.getPrincipals().add(new PlainRolePrincipal("USER")); subject.getPrincipals().add(new PlainRolePrincipal("ADMIN")); } log.debug("HAS USER " + getRequest().isUserInRole("USER")); log.debug("HAS ADMIN " + getRequest().isUserInRole("ADMIN")); log.debug("HAS REPORT " + getRequest().isUserInRole("REPORT")); session.setAttribute("javax.security.auth.subject", subject); log.debug("USER principal === " + getRequest().getUserPrincipal()); FacesContext.getCurrentInstance().getExternalContext() .redirect("pages/home.jsf"); } catch (ServletException e) { FacesContext.getCurrentInstance().addMessage("Login", new FacesMessage("Invalid Username/Password combination")); e.printStackTrace(); } } 

I also use the following bean information to retrieve the object and validate the participants.

  @ManagedBean(name = "userInfo") @SessionScoped public class UserInformation { /** * Fetches current logged in username. * * @return */ public String getUsername() { return FacesContext.getCurrentInstance().getExternalContext() .getRemoteUser(); } public boolean isUserInRole(String roleName) { Subject subject = (Subject) getRequest().getSession().getAttribute( "javax.security.auth.subject"); for (Principal p : subject.getPrincipals()) { if (p.getName().equals(roleName)) { return true; } } return false; } public static HttpServletRequest getRequest() { Object request = FacesContext.getCurrentInstance().getExternalContext() .getRequest(); return request instanceof HttpServletRequest ? (HttpServletRequest) request : null; } 

}

So, I will bypass the isUserInRole mechanism, the real isUserInRole method returns true only for USER, because this role is set during authentication.

On JSF pages I can now do

 <p:menuitem value="Create" action="#{menuController.XXXXXCreate}" ajax="false" helpText="Create new XXXXX" disabled="#{!userInfo.isUserInRole('ADMIN')}" /> 

We hope this helps other users, any suggestions for improvement are welcome!

+3
source

Source: https://habr.com/ru/post/907324/


All Articles