我正在使用GlassFish服務器4.0,我已將不同的權限/角色分配給不同的用戶。如何讓每個用戶根據其在JAAS中的權限/角色在特定位置訪問資源?
用戶可能擁有多個權限/角色。例如,管理員用戶可能與ROLE_ADMIN
(執行管理任務)和ROLE_USER
(作爲註冊用戶執行任務)相關聯。
在我的web.xml
中,配置如下。
<security-constraint>
<display-name>AdminConstraint</display-name>
<web-resource-collection>
<web-resource-name>ROLE_ADMIN</web-resource-name>
<description/>
<url-pattern>/admin_side/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>ROLE_ADMIN</role-name>
</auth-constraint>
<user-data-constraint>
<description/>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-constraint>
<display-name>UserConstraint</display-name>
<web-resource-collection>
<web-resource-name>ROLE_USER</web-resource-name>
<description/>
<url-pattern>/user_side/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description/>
<role-name>ROLE_USER</role-name>
</auth-constraint>
<user-data-constraint>
<description/>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<!--<auth-method>DIGEST</auth-method>-->
<auth-method>FORM</auth-method>
<realm-name>projectRealm</realm-name>
<form-login-config>
<form-login-page>/utility/Login.jsf</form-login-page>
<form-error-page>/utility/ErrorPage.jsf</form-error-page>
</form-login-config>
</login-config>
<security-role>
<description/>
<role-name>ROLE_ADMIN</role-name>
</security-role>
<security-role>
<description/>
<role-name>ROLE_USER</role-name>
</security-role>
這工作得很好。
有兩個URL模式/admin_side/*
和/user_side/*
。管理員有兩個角色ROLE_ADMIN
和ROLE_USER
。
當管理員使用權限ROLE_USER
登錄時,只有位於/user_side/*
中的資源應該被訪問。位於/admin_side/*
的資源應該被禁止訪問,因爲管理員以註冊用戶身份登錄,而不是以管理員身份登錄。
到現在爲止我的情況是,當管理員使用任何權限登錄時,兩個位置的資源都可以被訪問,這是完全非法的。這是因爲系統能夠爲該特定用戶找到兩個權威機構。
如何讓每個用戶根據其權限/角色訪問特定位置的資源?
認證過濾器:
@WebFilter(filterName = "SecurityCheck", urlPatterns = {"/jass/*"})
public final class SecurityCheck implements Filter
{
private FilterConfig filterConfig = null;
@Resource(mappedName="jms/destinationFactory")
private ConnectionFactory connectionFactory;
@Resource(mappedName="jms/destination")
private Queue queue;
@EJB
private final UserBeanLocal userService=null;
public SecurityCheck() {}
private void sendJMSMessageToDestination(String message) throws JMSException
{
Connection connection = null;
Session session = null;
try
{
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session.createProducer(queue);
TextMessage textMessage = session.createTextMessage();
textMessage.setText(message);
messageProducer.send(textMessage);
}
finally
{
if(session!=null){session.close();}
if(connection!=null){connection.close();}
}
}
private void doBeforeProcessing(ServletRequest request, ServletResponse response) throws IOException, ServletException
{
HttpServletRequest httpServletRequest=(HttpServletRequest)request;
httpServletRequest.login(httpServletRequest.getParameter("userName"), httpServletRequest.getParameter("password"));
}
private void doAfterProcessing(ServletRequest request, ServletResponse response) throws IOException, ServletException, JMSException
{
HttpServletRequest httpServletRequest=(HttpServletRequest)request;
HttpServletResponse httpServletResponse=(HttpServletResponse)response;
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
Map<String, Object> sessionMap = externalContext.getSessionMap();
if(httpServletRequest.isUserInRole("ROLE_USER"))
{
sendJMSMessageToDestination(httpServletRequest.getLocalName());
UserTable userTable = userService.setLastLogin(httpServletRequest.getParameter("userName"));
userTable.setPassword(null);
sessionMap.put("userName", userTable!=null?userTable.getFirstName():"Unknown");
sessionMap.put("user", userTable);
httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.sendRedirect("../user_side/Home.jsf");
}
else if(httpServletRequest.isUserInRole("ROLE_ADMIN"))
{
sendJMSMessageToDestination(httpServletRequest.getLocalName());
UserTable userTable = userService.setLastLogin(httpServletRequest.getParameter("userName"));
userTable.setPassword(null);
sessionMap.put("adminName", userTable!=null?userTable.getFirstName():"Unknown");
sessionMap.put("user", userTable);
httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.sendRedirect("../admin_side/Home.jsf");
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
try
{
doBeforeProcessing(request, response);
}
catch (Exception e)
{
HttpServletResponse httpServletResponse=(HttpServletResponse)response;
//FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "Incorrect user name and/or password. Access denied."));
httpServletResponse.sendRedirect("../utility/Login.jsf");
return;
}
chain.doFilter(request, response);
try
{
doAfterProcessing(request, response);
}
catch (JMSException ex)
{
Logger.getLogger(SecurityCheck.class.getName()).log(Level.SEVERE, null, ex);
}
}
//The rest of the filter.
}
如果你需要看其他的東西在我的應用程序的話,請讓我知道。
你到底是如何以註冊用戶身份登錄管理員的?如果一個特定的用戶有多個角色,那麼實際上沒有辦法只使用其中的一個登錄。所以整個問題很混亂。 – BalusC
這是一個驗證用戶身份的過濾器。過濾器映射到URL模式 - '/ jass/*'(錯誤地鍵入,應該是'/ jaas/*')。它指示一個目錄,其中只有一個頁面 - 調用JSF頁面上的登錄按鈕時(通過其相應的JSF託管bean)調度請求的'temp.jsp'。有沒有辦法一次作爲管理員登錄和一次使用相同的ID /密碼的用戶登錄?我也覺得如此,但認爲容器可能支持一些機制來做到這一點。我看了一些教程,但一無所知。 – Tiny