Coe*_*men 6 java authentication jsf glassfish-3
我有以下JSF 2.1登录表单,在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>
Run Code Online (Sandbox Code Playgroud)
以及支持bean.
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";
}
Run Code Online (Sandbox Code Playgroud)
问题是,如何在成功登录后以编程方式将角色添加到UserPrincipal?
更新1:我试图通过使用以下代码获取主题但主题== null.
Subject thisSubject = Subject.getSubject(AccessController
.getContext());
Run Code Online (Sandbox Code Playgroud)
谢谢,科恩
我想出了以下解决方案,在登录后以编程方式添加角色,至少在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);
}
}
Run Code Online (Sandbox Code Playgroud)
您将需要添加security.jar并common-util.jar从GlassFish在您的项目库.
并且不要忘记<security-role>在web.xml中为要添加的角色创建一个部分.
请注意,我使用的功能似乎不是已发布的稳定API的一部分,因此无法保证这将在将来的GlassFish版本中继续使用.
我获得了有关如何从sun.appserv.security.AppservPasswordLoginModule.commit()GlassFish 的源代码添加角色的信息.如果未来的GlassFish版本破坏了我的代码,这个函数将是一个很好的起点,以便找到解决方法.
好的,我已经找到了一个解决方法,在我看来这并不是 100% 正确,但欢迎提出建议:)
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();
}
}
Run Code Online (Sandbox Code Playgroud)
我还使用以下信息 bean 来检索主题并检查主体。
@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;
}
Run Code Online (Sandbox Code Playgroud)
}
因此,我解决了 isUserInRole 机制,真正的 isUserInRole 方法仅在 USER 上返回 true,因为该角色是在身份验证时设置的。
从 JSF 页面我现在可以做
<p:menuitem value="Create" action="#{menuController.XXXXXCreate}"
ajax="false" helpText="Create new XXXXX"
disabled="#{!userInfo.isUserInRole('ADMIN')}" />
Run Code Online (Sandbox Code Playgroud)
希望这对其他用户有所帮助,欢迎任何改进建议!
| 归档时间: |
|
| 查看次数: |
16993 次 |
| 最近记录: |