Server JAVA 讲座----用自定义functionality实现用户权限控制

有了上此讲座的基础,我想理解我们这个功能应该就很容易了。刚刚我们经理问我有用户希望控制web登陆用户的权限,那么我们正好利用这个讲座来看看如何实现这个功能。我们新建一个类,functionality当然要实现GISFunctionality接口了:
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-comfficeffice" />
public class SecurityCheckFunctionality implements GISFunctionality {
private AGSMapResource resource;
  public void initFunctionality(GISResource resource) { //empty }
public void destroyFunctionality() { //empty  }
  public GISResource getResource() { //empty  }
}

我们在这里放了一个AGSMapResource类型的变量,因为我们需要对Resource进行很多操作,我们来看一下:
public void initFunctionality(GISResource resource) {
this.resource = (AGSMapResource)resource; //得到资源
    //查看用户是否属于"petroEmployee" 角色
   if(!WebUtil.getExternalContext().isUserInRole("pretroEmployee")){
   //从Resource中得到MapFunctionality
  AGSMapFunctionality mapFunc = (AGSMapFunctionality)resource.getFunctionality("map");

   //得到对 MapServerInfo的引用
   MapServerInfo serverInfo = mapFunc.getMapServerInfo();
   //得到 "Pipeline_Network" 层
MapLayerInfo pipelineLayerInfo = AGSUtil.getLayerInfo("PipeLine_Network",layerInfos);
     if(pipelineLayerInfo==null)
      return; //层不存在,return.
      //从TOC中移除
      MapLayerInfo[] newLayerInfos =  removeLayer(pipelineLayerInfo,layerInfos);
      serverInfo.setMapLayerInfos(newLayerInfos);
      //从MAP中移除
      LayerDescription[] layerDescriptions =serverInfo.getDefaultMapDescription().getLayerDescriptions();
     //新建一个层描述,替换原来的层描述
      LayerDescription[] newLayerDescriptions = new LayerDescription[newLayerInfos.length];

      for(int i=0;i<newLayerInfos.length;i++){
    newLayerDescriptions=AGSUtil.getLayerDescription(newLayerInfos.getLayerID(),layerDescriptions);
5                                                                                    serverInfo.getDefaultMapDescription().setLayerDescriptions(newLayerDescriptions);
    }
  }

上面的代码中用removeLayer(pipelineLayerInfo,layerInfos);函数移除了要移除的层,然后更新了TOC和MAP,我们来看看这个函数怎么来写:
//Logic to remove a layer and all its descendants
  private MapLayerInfo[] removeLayer(MapLayerInfo unwantedLayerInfo, MapLayerInfo[] oldLayerInfos) {
        //新建一个MapLayerInfo
    MapLayerInfo[] newLayerInfos = new MapLayerInfo[oldLayerInfos.length-1];
    ArrayList descendantLayers = new ArrayList();
    for(int i=0,j=0;i<oldLayerInfos.length;i++){
      if(oldLayerInfos.getLayerID()!=unwantedLayerInfo.getLayerID())
        newLayerInfos[j++] = oldLayerInfos;
      if(oldLayerInfos.getParentLayerID()==unwantedLayerInfo.getLayerID())
        descendantLayers.add(oldLayerInfos);
  }
    for(int i=0;i<descendantLayers.size();i++){
newLayerInfos = removeLayer((MapLayerInfo)descendantLayers.get(i),newLayerInfos);
    }
    return newLayerInfos;
  }

我们注意到这是一个递归函数,用于把该层下面所有的其它附属层都删除:

这个functionality写完了,我们来看看如何部署,部署的时候,先把它作为一个Managed Bean部署,用下面可代码即可,可以在faces-config.xml文件里面,也可以在ags-functionality.xml里面:
<managed-bean>
    <managed-bean-name>securitycheck</managed-bean-name>
     <managed-bean-class>com.mypackage.SecurityCheckFunctionality</managed-bean-class>
    <managed-bean-scope>none</managed-bean-scope>
</managed-bean>

将它作为一个managedBean部署后,下面就把它部署到resource中,注意部署的时候,要将其部署到map之后,toc之前,因为ADF初始化是按顺序初始化,我们的权限控制需要从Map中读出层的信息,然后修改MapDesc,从而影响TOC的信息,所以,进行如下的部署配置:
<managed-bean>
    <managed-bean-name>ags1</managed-bean-name>
    <managed-bean-class>
    com.esri.adf.web.ags.data.AGSLocalMapResource
  </managed-bean-class>
   <managed-bean-scope>none</managed-bean-scope>
  ...
  <managed-property>
    <property-name>functionalities</property-name>
    <map-entries>
      <map-entry>
<key>map</key>
<value>#{agsMap}</value>
      </map-entry>
      <map-entry>
<key>query</key>
<value>#{agsQuery}</value>
      </map-entry>
      <map-entry>
<key>tile</key>
<value>#{agsTile}</value>
      </map-entry>
      <map-entry>
<key>overview</key>
<value>#{agsOverview}</value>
      </map-entry>
      <map-entry>
<key>pipeline_security_check</key>
<value>#{securitycheck}</value>
      </map-entry>
      <map-entry>
<key>toc</key>
<value>#{agsToc}</value>
      </map-entry>
    </map-entries>
  </managed-property>
</managed-bean>

OK,这个安全控制的functionality已经完成了。但是我们要对整个WebApplication加上安全控制,需要在web.xml做修改,添加如下的配置:
<login-config>
<auth-method>DIGEST</auth-method>
  <realm-name>My_WebApplication</realm-name>
</login-config>
//声明两个组用户
<security-role>
  <role-name>petroEmployee</role-name>
</security-role>

<security-role>
  <role-name>stateEmployee</role-name>
</security-role>

//声明什么资源将收到安全控制,这里我们把整个目录都控制,当然你也可以控制胆敢目录
<security-constraint>
  <web-resource-collection>
<url-pattern>*<url-pattern>
  </web-resource-collection>
  <auth-constraint>
<role-name>petroEmployee</role-name>
<role-name>stateEmployee<role-name>
</auth-constraint>
</security-constraint>

这两个组在什么地方定义呢?如果是Tomcat,我们可以在$TOMCAT_HOME/conf/tomcat-users.xml中定义,定义如下:
<tomcat-users>  ...
  <user name="joe" password="joe" roles="petroEmployee">
  <user name="daisy" password="daisy" roles="stateEmployee">
  ...
</tomcat-users>

这样我们就控制了整个Web Application,并且对于不同的用户组,赋予了不同的层的查看权限。每次用户访问这个网站的时候,都会被提示要求输入用户名和密码,按照我们在Tomcat-users里面的定义进行输入即可。

还有用户会问道,如果我希望对属性字段的编辑进行控制怎么办;事实上原理是类似的,你让用户修改属性字段时,肯定要传输一个字段列表,你可以根据不同的用户组,对这个字段列表进行控制。

另外,这里我们用了WEB容器的用户和权限进行控制,事实上你不必依赖于Web容器,你可以在数据库中存放你自己定义的用户名和组,进行控制。
权限控制简单的讲就是这样子,.net里面也类似,有机会的话,我会写一个.net版本的给大家看看。

注:本讲座内容参考了并翻译了ESRI的JAVA帮助的部分内容。










你可能感兴趣的:(java,tomcat,Web,.net,xml)