NIHVIVO-2492 First pass at a mechanism to restrict pages by policy
This commit is contained in:
parent
32e4f81be7
commit
83ac0750b5
10 changed files with 530 additions and 23 deletions
|
@ -49,4 +49,33 @@
|
||||||
</attribute>
|
</attribute>
|
||||||
</tag>
|
</tag>
|
||||||
|
|
||||||
|
<tag>
|
||||||
|
<name>requiresAuthorizationFor</name>
|
||||||
|
<display-name>Confirm that the user is authorized for the actions that this page requires.</display-name>
|
||||||
|
<description>
|
||||||
|
Confirm that the user is authorized to perform all of the RequestedActions that
|
||||||
|
this page requires. A check is done for each such action, to see whether the
|
||||||
|
current policy will authorize that action for the current user. If any of the
|
||||||
|
actions is not authorized, the user will be redirected to the appropriate page.
|
||||||
|
|
||||||
|
If the user is not authorized because he is not logged in, he will be directed
|
||||||
|
to the login page, with the current request stored as a post-login destination.
|
||||||
|
|
||||||
|
If the user is logged in but without sufficient authorization, he will be
|
||||||
|
directed to the home page, which will display an "insufficient authorization"
|
||||||
|
message.
|
||||||
|
|
||||||
|
The requested actions are specified as a comma delimited list of names (with
|
||||||
|
optional spaces). These names must match against the map of classes in
|
||||||
|
JspPolicyHelper, or an error will be logged and the authorization will fail.
|
||||||
|
</description>
|
||||||
|
<tag-class>edu.cornell.mannlib.vitro.webapp.web.jsptags.RequiresAuthorizationFor</tag-class>
|
||||||
|
<body-content>empty</body-content>
|
||||||
|
<attribute>
|
||||||
|
<name>actions</name>
|
||||||
|
<required>true</required>
|
||||||
|
<rtexprvalue>true</rtexprvalue>
|
||||||
|
</attribute>
|
||||||
|
</tag>
|
||||||
|
|
||||||
</taglib>
|
</taglib>
|
|
@ -0,0 +1,211 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.auth.policy;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper.RequiresAuthorizationFor.NoAction;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A collection of static methods to help determine whether requested actions
|
||||||
|
* are authorized by current policy.
|
||||||
|
*/
|
||||||
|
public class PolicyHelper {
|
||||||
|
private static final Log log = LogFactory.getLog(PolicyHelper.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A subclass of VitroHttpServlet may be annotated to say what actions
|
||||||
|
* should be checked for authorization before permitting the user to view
|
||||||
|
* the page that the servlet would create.
|
||||||
|
*
|
||||||
|
* Any RequestedAction can be specified, but the most common use will be to
|
||||||
|
* specify implementations of UsePagesRequestedAction.
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
public static @interface RequiresAuthorizationFor {
|
||||||
|
static class NoAction extends RequestedAction {
|
||||||
|
/* no fields */
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<? extends RequestedAction>[] value() default NoAction.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this servlet require authorization?
|
||||||
|
*/
|
||||||
|
public static boolean isRestrictedPage(VitroHttpServlet servlet) {
|
||||||
|
Class<? extends VitroHttpServlet> servletClass = servlet.getClass();
|
||||||
|
return !getRequiredAuthorizationsForServlet(servletClass).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* What RequestedActions does this servlet require authorization for?
|
||||||
|
*/
|
||||||
|
public static Set<RequestedAction> getRequiredAuthorizationsForServlet(
|
||||||
|
Class<? extends VitroHttpServlet> clazz) {
|
||||||
|
Set<RequestedAction> result = new HashSet<RequestedAction>();
|
||||||
|
|
||||||
|
RequiresAuthorizationFor annotation = clazz
|
||||||
|
.getAnnotation(RequiresAuthorizationFor.class);
|
||||||
|
|
||||||
|
if (annotation != null) {
|
||||||
|
for (Class<? extends RequestedAction> actionClass : annotation
|
||||||
|
.value()) {
|
||||||
|
if (NoAction.class != actionClass) {
|
||||||
|
RequestedAction action = instantiateAction(actionClass);
|
||||||
|
if (action != null) {
|
||||||
|
result.add(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are the actions that this servlet requires authorized for the current
|
||||||
|
* user by the current policies?
|
||||||
|
*/
|
||||||
|
public static boolean areRequiredAuthorizationsSatisfied(
|
||||||
|
HttpServletRequest req, VitroHttpServlet servlet) {
|
||||||
|
Class<? extends VitroHttpServlet> servletClass = servlet.getClass();
|
||||||
|
return areRequiredAuthorizationsSatisfied(req,
|
||||||
|
getRequiredAuthorizationsForServlet(servletClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are these action classes authorized for the current user by the current
|
||||||
|
* policies?
|
||||||
|
*/
|
||||||
|
public static boolean areRequiredAuthorizationsSatisfied(
|
||||||
|
HttpServletRequest req,
|
||||||
|
Class<? extends RequestedAction>... actionClasses) {
|
||||||
|
List<Class<? extends RequestedAction>> classList = Arrays
|
||||||
|
.asList(actionClasses);
|
||||||
|
|
||||||
|
Set<RequestedAction> actions = instantiateActions(classList);
|
||||||
|
if (actions == null) {
|
||||||
|
log.debug("not authorized: failed to instantiate actions");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return areRequiredAuthorizationsSatisfied(req, actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are these actions authorized for the current user by the current
|
||||||
|
* policies?
|
||||||
|
*/
|
||||||
|
public static boolean areRequiredAuthorizationsSatisfied(
|
||||||
|
HttpServletRequest req,
|
||||||
|
Collection<? extends RequestedAction> actions) {
|
||||||
|
PolicyIface policy = ServletPolicyList.getPolicies(req);
|
||||||
|
IdentifierBundle ids = RequestIdentifiers.getIdBundleForRequest(req);
|
||||||
|
|
||||||
|
for (RequestedAction action : actions) {
|
||||||
|
if (isAuthorized(policy, ids, action)) {
|
||||||
|
log.debug("not authorized");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("authorized");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this action class authorized for the current user by the current
|
||||||
|
* policies?
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static boolean isAuthorized(HttpServletRequest req,
|
||||||
|
Class<? extends RequestedAction> actionClass) {
|
||||||
|
return areRequiredAuthorizationsSatisfied(req, actionClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this action authorized for these IDs by this policy?
|
||||||
|
*/
|
||||||
|
private static boolean isAuthorized(PolicyIface policy,
|
||||||
|
IdentifierBundle ids, RequestedAction action) {
|
||||||
|
PolicyDecision decision = policy.isAuthorized(ids, action);
|
||||||
|
log.debug("decision for '" + action.getClass().getName() + "' was: "
|
||||||
|
+ decision);
|
||||||
|
return (decision == null)
|
||||||
|
|| (decision.getAuthorized() != Authorization.AUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate actions from their classes. If any one of the classes cannot
|
||||||
|
* be instantiated, return null.
|
||||||
|
*/
|
||||||
|
private static Set<RequestedAction> instantiateActions(
|
||||||
|
Collection<Class<? extends RequestedAction>> actionClasses) {
|
||||||
|
Set<RequestedAction> actions = new HashSet<RequestedAction>();
|
||||||
|
for (Class<? extends RequestedAction> actionClass : actionClasses) {
|
||||||
|
RequestedAction action = instantiateAction(actionClass);
|
||||||
|
if (action == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
actions.add(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an instance of the RequestedAction, from its class. If the class
|
||||||
|
* cannot be instantiated, return null.
|
||||||
|
*/
|
||||||
|
private static RequestedAction instantiateAction(
|
||||||
|
Class<? extends RequestedAction> actionClass) {
|
||||||
|
try {
|
||||||
|
Constructor<? extends RequestedAction> constructor = actionClass
|
||||||
|
.getConstructor();
|
||||||
|
RequestedAction instance = constructor.newInstance();
|
||||||
|
return instance;
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
log.error("'" + actionClass.getName()
|
||||||
|
+ "' does not have a no-argument constructor.");
|
||||||
|
return null;
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
log.error("The no-argument constructor for '"
|
||||||
|
+ actionClass.getName() + "' is not public.");
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to instantiate '" + actionClass.getName() + "'",
|
||||||
|
e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No need to instantiate this helper class - all methods are static.
|
||||||
|
*/
|
||||||
|
private PolicyHelper() {
|
||||||
|
// nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.auth.policy;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.HasRoleLevel;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.Identifier;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.Authorization;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyDecision;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ifaces.PolicyIface;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseAdvancedDataToolsPages;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean.RoleLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the users role level to determine whether they are allowed to use
|
||||||
|
* restricted pages.
|
||||||
|
*/
|
||||||
|
public class UseRestrictedPagesByRoleLevelPolicy implements PolicyIface {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(UseRestrictedPagesByRoleLevelPolicy.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PolicyDecision isAuthorized(IdentifierBundle whoToAuth,
|
||||||
|
RequestedAction whatToAuth) {
|
||||||
|
if (whoToAuth == null) {
|
||||||
|
return defaultDecision("whomToAuth was null");
|
||||||
|
}
|
||||||
|
if (whatToAuth == null) {
|
||||||
|
return defaultDecision("whatToAuth was null");
|
||||||
|
}
|
||||||
|
|
||||||
|
RoleLevel userRole = getUsersRoleLevel(whoToAuth);
|
||||||
|
|
||||||
|
PolicyDecision result;
|
||||||
|
if (whatToAuth instanceof UseAdvancedDataToolsPages) {
|
||||||
|
result = isAuthorized(whatToAuth, RoleLevel.DB_ADMIN, userRole);
|
||||||
|
} else {
|
||||||
|
result = defaultDecision("Unrecognized action");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("decision for '" + whatToAuth + "' is " + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PolicyDecision isAuthorized(RequestedAction whatToAuth,
|
||||||
|
RoleLevel requiredRole, RoleLevel currentRole) {
|
||||||
|
if (isRoleAtLeast(requiredRole, currentRole)) {
|
||||||
|
return authorized("User may view page: " + whatToAuth
|
||||||
|
+ ", requiredRole=" + requiredRole + ", currentRole="
|
||||||
|
+ currentRole);
|
||||||
|
} else {
|
||||||
|
return defaultDecision("User may not view page: " + whatToAuth
|
||||||
|
+ ", requiredRole=" + requiredRole + ", currentRole="
|
||||||
|
+ currentRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRoleAtLeast(RoleLevel required, RoleLevel current) {
|
||||||
|
return (current.compareTo(required) >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** If the user is explicitly authorized, return this. */
|
||||||
|
private PolicyDecision authorized(String message) {
|
||||||
|
String className = this.getClass().getSimpleName();
|
||||||
|
return new BasicPolicyDecision(Authorization.AUTHORIZED, className
|
||||||
|
+ ": " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** If the user isn't explicitly authorized, return this. */
|
||||||
|
private PolicyDecision defaultDecision(String message) {
|
||||||
|
return new BasicPolicyDecision(Authorization.INCONCLUSIVE, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user is nobody unless they have a HasRoleLevel identifier.
|
||||||
|
*/
|
||||||
|
private RoleLevel getUsersRoleLevel(IdentifierBundle whoToAuth) {
|
||||||
|
RoleLevel userRole = RoleLevel.PUBLIC;
|
||||||
|
for (Identifier id : whoToAuth) {
|
||||||
|
if (id instanceof HasRoleLevel) {
|
||||||
|
userRole = ((HasRoleLevel) id).getRoleLevel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userRole;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ import edu.cornell.mannlib.vitro.webapp.auth.identifier.CommonIdentifierBundleFa
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.DisplayRestrictedDataByRoleLevelPolicy;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.DisplayRestrictedDataByRoleLevelPolicy;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.DisplayRestrictedDataToSelfPolicy;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.DisplayRestrictedDataToSelfPolicy;
|
||||||
import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList;
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.UseRestrictedPagesByRoleLevelPolicy;
|
||||||
import edu.cornell.mannlib.vitro.webapp.servlet.setup.AbortStartup;
|
import edu.cornell.mannlib.vitro.webapp.servlet.setup.AbortStartup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,6 +37,8 @@ public class CommonPolicyFamilySetup implements ServletContextListener {
|
||||||
new DisplayRestrictedDataByRoleLevelPolicy(ctx));
|
new DisplayRestrictedDataByRoleLevelPolicy(ctx));
|
||||||
ServletPolicyList.addPolicy(ctx,
|
ServletPolicyList.addPolicy(ctx,
|
||||||
new DisplayRestrictedDataToSelfPolicy(ctx));
|
new DisplayRestrictedDataToSelfPolicy(ctx));
|
||||||
|
ServletPolicyList.addPolicy(ctx,
|
||||||
|
new UseRestrictedPagesByRoleLevelPolicy());
|
||||||
|
|
||||||
// This factory creates Identifiers for all of the above policies.
|
// This factory creates Identifiers for all of the above policies.
|
||||||
CommonIdentifierBundleFactory factory = new CommonIdentifierBundleFactory();
|
CommonIdentifierBundleFactory factory = new CommonIdentifierBundleFactory();
|
||||||
|
|
|
@ -12,4 +12,8 @@ public abstract class RequestedAction {
|
||||||
return RequestActionConstants.actionNamespace + this.getClass().getName();
|
return RequestActionConstants.actionNamespace + this.getClass().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.getClass().getSimpleName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||||
|
|
||||||
|
/** Should we allow the user to use the pages for Advanced Data Tools? */
|
||||||
|
public class UseAdvancedDataToolsPages extends RequestedAction implements
|
||||||
|
UsePagesRequestedAction {
|
||||||
|
// no fields
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages;
|
||||||
|
|
||||||
|
/** Denotes a request to use a particular page or group of pages. */
|
||||||
|
public interface UsePagesRequestedAction {
|
||||||
|
/** marker interface */
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage;
|
import edu.cornell.mannlib.vitro.webapp.beans.DisplayMessage;
|
||||||
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.LogoutRedirector;
|
import edu.cornell.mannlib.vitro.webapp.controller.authenticate.LogoutRedirector;
|
||||||
|
|
||||||
|
@ -44,6 +45,38 @@ public class VitroHttpServlet extends HttpServlet {
|
||||||
public final static String TTL_MIMETYPE = "text/turtle"; // unofficial and
|
public final static String TTL_MIMETYPE = "text/turtle"; // unofficial and
|
||||||
// unregistered
|
// unregistered
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that any required authorizations are satisfied before processing
|
||||||
|
* the request.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final void service(ServletRequest req, ServletResponse resp)
|
||||||
|
throws ServletException, IOException {
|
||||||
|
if ((req instanceof HttpServletRequest)
|
||||||
|
&& (resp instanceof HttpServletResponse)) {
|
||||||
|
HttpServletRequest hreq = (HttpServletRequest) req;
|
||||||
|
HttpServletResponse hresp = (HttpServletResponse) resp;
|
||||||
|
|
||||||
|
if (log.isTraceEnabled()) {
|
||||||
|
dumpRequestHeaders(hreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PolicyHelper.isRestrictedPage(this)) {
|
||||||
|
LogoutRedirector.recordRestrictedPageUri(hreq);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PolicyHelper.areRequiredAuthorizationsSatisfied(hreq, this)) {
|
||||||
|
if (LoginStatusBean.getBean(hreq).isLoggedIn()) {
|
||||||
|
redirectToInsufficientAuthorizationPage(hreq, hresp);
|
||||||
|
} else {
|
||||||
|
redirectToLoginPage(hreq, hresp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.service(req, resp);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show this to the user if they are logged in, but still not authorized to
|
* Show this to the user if they are logged in, but still not authorized to
|
||||||
* view the page.
|
* view the page.
|
||||||
|
@ -87,6 +120,8 @@ public class VitroHttpServlet extends HttpServlet {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If not logged in, redirect them to the login page.
|
* If not logged in, redirect them to the login page.
|
||||||
|
*
|
||||||
|
* TODO this goes away as it is replace by annotations.
|
||||||
*/
|
*/
|
||||||
public static boolean checkLoginStatus(HttpServletRequest request,
|
public static boolean checkLoginStatus(HttpServletRequest request,
|
||||||
HttpServletResponse response) {
|
HttpServletResponse response) {
|
||||||
|
@ -104,6 +139,8 @@ public class VitroHttpServlet extends HttpServlet {
|
||||||
/**
|
/**
|
||||||
* If not logged in at the required level, redirect them to the appropriate
|
* If not logged in at the required level, redirect them to the appropriate
|
||||||
* page.
|
* page.
|
||||||
|
*
|
||||||
|
* TODO this goes away as it is replace by annotations.
|
||||||
*/
|
*/
|
||||||
public static boolean checkLoginStatus(HttpServletRequest request,
|
public static boolean checkLoginStatus(HttpServletRequest request,
|
||||||
HttpServletResponse response, int minimumLevel) {
|
HttpServletResponse response, int minimumLevel) {
|
||||||
|
@ -183,24 +220,17 @@ public class VitroHttpServlet extends HttpServlet {
|
||||||
* If logging is set to the TRACE level, dump the HTTP headers on the
|
* If logging is set to the TRACE level, dump the HTTP headers on the
|
||||||
* request.
|
* request.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
private void dumpRequestHeaders(HttpServletRequest req) {
|
||||||
@Override
|
@SuppressWarnings("unchecked")
|
||||||
public void service(ServletRequest req, ServletResponse resp)
|
Enumeration<String> names = req.getHeaderNames();
|
||||||
throws ServletException, IOException {
|
|
||||||
if (log.isTraceEnabled()) {
|
log.trace("----------------------request:" + req.getRequestURL());
|
||||||
HttpServletRequest request = (HttpServletRequest) req;
|
while (names.hasMoreElements()) {
|
||||||
Enumeration<String> names = request.getHeaderNames();
|
String name = names.nextElement();
|
||||||
log.trace("----------------------request:"
|
if (!BORING_HEADERS.contains(name)) {
|
||||||
+ request.getRequestURL());
|
log.trace(name + "=" + req.getHeader(name));
|
||||||
while (names.hasMoreElements()) {
|
|
||||||
String name = names.nextElement();
|
|
||||||
if (!BORING_HEADERS.contains(name)) {
|
|
||||||
log.trace(name + "=" + request.getHeader(name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super.service(req, resp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Don't dump the contents of these headers, even if log.trace is enabled. */
|
/** Don't dump the contents of these headers, even if log.trace is enabled. */
|
||||||
|
|
|
@ -16,13 +16,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.authenticate.LogoutRedirector
|
||||||
import edu.cornell.mannlib.vitro.webapp.filters.VitroRequestPrep;
|
import edu.cornell.mannlib.vitro.webapp.filters.VitroRequestPrep;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSP tag to generate the HTML of links for edit, delete or add of a Property.
|
* TODO This should go away as it is replaced by vitro:requiresAuthorizationFor
|
||||||
*
|
|
||||||
* Maybe we should have a mode where it just sets a var to a map with "href" =
|
|
||||||
* "edit/editDatapropDispatch.jsp?subjectUri=..." and "type" = "delete"
|
|
||||||
*
|
|
||||||
* @author bdc34
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public class ConfirmLoginStatus extends BodyTagSupport {
|
public class ConfirmLoginStatus extends BodyTagSupport {
|
||||||
private static final Log log = LogFactory.getLog(ConfirmLoginStatus.class);
|
private static final Log log = LogFactory.getLog(ConfirmLoginStatus.class);
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.web.jsptags;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.jsp.JspException;
|
||||||
|
import javax.servlet.jsp.tagext.BodyTagSupport;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.ifaces.RequestedAction;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.UseAdvancedDataToolsPages;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm that the user is authorized to perform each of the RequestedActions.
|
||||||
|
*
|
||||||
|
* The user specifies the actions as a comma delimited list of names (with
|
||||||
|
* optional spaces). These names are matched against the map of recognized
|
||||||
|
* names. If no match is found, an error is logged and the authorization fails.
|
||||||
|
*/
|
||||||
|
public class RequiresAuthorizationFor extends BodyTagSupport {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(RequiresAuthorizationFor.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are the only action names that we recognize.
|
||||||
|
*/
|
||||||
|
private static final Map<String, RequestedAction> actionMap = new HashMap<String, RequestedAction>();
|
||||||
|
static {
|
||||||
|
actionMap.put("UseAdvancedDataToolsPages",
|
||||||
|
new UseAdvancedDataToolsPages());
|
||||||
|
}
|
||||||
|
|
||||||
|
String actionNames = "";
|
||||||
|
|
||||||
|
public void setActions(String actionNames) {
|
||||||
|
this.actionNames = actionNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is all of it. If they are authorized, continue. Otherwise, redirect.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int doEndTag() throws JspException {
|
||||||
|
if (isAuthorized()) {
|
||||||
|
return EVAL_PAGE;
|
||||||
|
} else if (isLoggedIn()) {
|
||||||
|
return showInsufficientAuthorizationMessage();
|
||||||
|
} else {
|
||||||
|
return redirectToLoginPage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* They are authorized if we recognize the actions they ask for, and they
|
||||||
|
* are authorized for those actions.
|
||||||
|
*/
|
||||||
|
private boolean isAuthorized() {
|
||||||
|
Collection<RequestedAction> actions = parseActionNames();
|
||||||
|
if (actions == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return PolicyHelper.areRequiredAuthorizationsSatisfied(getRequest(),
|
||||||
|
actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the string and pull the corresponding actions from the map. If we
|
||||||
|
* can't do that, complain and return null.
|
||||||
|
*/
|
||||||
|
private Collection<RequestedAction> parseActionNames() {
|
||||||
|
Set<RequestedAction> actions = new HashSet<RequestedAction>();
|
||||||
|
|
||||||
|
for (String part : actionNames.split("[\\s],[\\s]")) {
|
||||||
|
String key = part.trim();
|
||||||
|
if (key.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actionMap.containsKey(key)) {
|
||||||
|
log.debug("checking authorization for '" + key + "'");
|
||||||
|
actions.add(actionMap.get(key));
|
||||||
|
} else {
|
||||||
|
log.error("JSP requested authorization for unknown action: '"
|
||||||
|
+ key + "'");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLoggedIn() {
|
||||||
|
return LoginStatusBean.getBean(getRequest()).isLoggedIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int showInsufficientAuthorizationMessage() {
|
||||||
|
VitroHttpServlet.redirectToInsufficientAuthorizationPage(getRequest(),
|
||||||
|
getResponse());
|
||||||
|
return SKIP_PAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int redirectToLoginPage() throws JspException {
|
||||||
|
VitroHttpServlet.redirectToLoginPage(getRequest(), getResponse());
|
||||||
|
return SKIP_PAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpServletRequest getRequest() {
|
||||||
|
return ((HttpServletRequest) pageContext.getRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpServletResponse getResponse() {
|
||||||
|
return (HttpServletResponse) pageContext.getResponse();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue