/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.citrus.turbine.pipeline.valve; import static com.alibaba.citrus.springext.util.SpringExtUtil.*; import static com.alibaba.citrus.turbine.util.TurbineUtil.*; import static com.alibaba.citrus.util.ArrayUtil.*; import static com.alibaba.citrus.util.CollectionUtil.*; import static com.alibaba.citrus.util.StringUtil.*; import java.util.List; import javax.servlet.http.HttpServletRequest; import com.alibaba.citrus.service.pipeline.PipelineContext; import com.alibaba.citrus.service.pipeline.support.AbstractValve; import com.alibaba.citrus.service.pipeline.support.AbstractValveDefinitionParser; import com.alibaba.citrus.turbine.TurbineRunData; import com.alibaba.citrus.turbine.auth.PageAuthorizationService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; public class PageAuthorizationValve extends AbstractValve { @Autowired private HttpServletRequest request; @Autowired private PageAuthorizationService pageAuthorizationService; private Callback<?> callback; public void setCallback(Callback<?> callback) { this.callback = callback; } @Override protected void init() throws Exception { if (callback == null) { callback = new DefaultCallback(); } } public void invoke(PipelineContext pipelineContext) throws Exception { TurbineRunData rundata = getTurbineRunData(request); @SuppressWarnings("unchecked") Callback<Object> cb = (Callback<Object>) callback; Object status = cb.onStart(rundata); String userName = cb.getUserName(status); String[] roleNames = cb.getRoleNames(status); String target = rundata.getTarget(); String action = rundata.getAction(); String event = capitalize(rundata.getActionEvent()); // 取得当前请求的actions,包括三部分: // 1. screen // 2. action.*.event - 假如请求包含action参数的话 // 3. callback返回的额外actions // 只有当所有action全部被授权时,请求才会继续处理下去。 List<String> actions = createLinkedList(); actions.add("screen"); if (action != null) { if (event != null) { actions.add("action." + action + ".do" + event); } else { actions.add("action." + action); } } String[] extraActions = cb.getActions(status); if (!isEmptyArray(extraActions)) { for (String extraAction : extraActions) { actions.add(extraAction); } } // 检查权限,根据: // 1. 当前的target // 2. 当前的user和roles // 3. 将要执行的actions,例如:screen、action.xxx.UserAction if (pageAuthorizationService.isAllow(target, userName, roleNames, actions.toArray(new String[actions.size()]))) { cb.onAllow(status); pipelineContext.invokeNext(); } else { cb.onDeny(status); // end of pipeline } } public interface Callback<T> { String getUserName(T status); String[] getRoleNames(T status); String[] getActions(T status); T onStart(TurbineRunData rundata) throws Exception; void onAllow(T status) throws Exception; void onDeny(T status) throws Exception; } private class DefaultCallback implements Callback<TurbineRunData> { public String getUserName(TurbineRunData status) { return null; } public String[] getRoleNames(TurbineRunData status) { return null; } public String[] getActions(TurbineRunData status) { return null; } public TurbineRunData onStart(TurbineRunData rundata) { return rundata; } public void onAllow(TurbineRunData status) throws Exception { } public void onDeny(TurbineRunData status) { } } public static class DefinitionParser extends AbstractValveDefinitionParser<PageAuthorizationValve> { @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { element.setAttribute("class", element.getAttribute("callbackClass")); builder.addPropertyValue("callback", parseBean(element, parserContext, builder)); } } }