这次讲解如何控制用户登录,如何拦截 URL 进行权限验证。
 
通常,项目有这样的需求:
 
某些页面没有登录可以查看;
某些页面必须登录才能查看,如果没有登录,转移到登录页面,成功登录后再转移回来;
某些页面必须验证当前登录用户是否具有请求该页面的权限,如果没有转移到权限不足提示界面。
 
解决思路控制登录控制用户登录,采用 Filter 机制,不妨给该 Filter 起名为 LoginFilter 。
怎样控制哪些页面验证是否登录,哪些又不需要呢?配置 web.xml , filter 元素的 url-pattern 属性就可以了。
如:
Xml代码 
<filter-mapping>  
              <filter-name>LoginFilter</filter-name>  
              <url-pattern>/secretDir/*</url-pattern>  
</filter-mapping>  
  
<filter-mapping>  
              <filter-name>LoginFilter</filter-name>  
              <url-pattern>/anotherDir/secretDir/*</url-pattern>  
</filter-mapping>  
 
 
 
LoginFilter 检查 session 是否有用户,如果没有转移到登录页面;否则继续执行。
伪代码如下:
Java代码 
if( session.getAttribute( “user” )==null ) {  
       // 将用户期望请求页面保存到session,供用户登录成功后,自动跳转使用  
       String requestUrl=…;  
       session.setAttribute( “requestUrl”, requestUrl );   
  
       // 转移到登录界面  
       redirect( loginPage, request, response );  
       return;  
}  
  
filter.doChain( request, response );  
 
 
 
LoginFilter 还可以更进一步,处理用户提交用户名和密码后验证。只要告诉 LoginFilter 用户名是哪个 parameter name ,密码是哪个parameter name ,密码采用了什么加密算法,就可以了。
伪代码如下:
Java代码 
String username=request.getParameter( usernameParameterName );  
String password=request.getParameter( passwordParameterName );  
String secretPassword=encrypt(encryptMethod, password );  
   
  
User user=userManager.checkUser( username, secretPassword );  
if( user==null ) {  
       // 验证不通过,继续转移到登录界面  
       redirect( loginPage, request, response );  
} else {  
       // 验证通过,将用户保存到session,然后继续处理  
       session.removeAttribute( “requestUrl” );  
       session.setAttribute( “user”, user );  
       filter.doChain( request, response );  
}  
 
 
 
细心的朋友,会问转移到原来期望请求的页面,怎么没有看到逻辑呢?
是的,可以在该 filter 里面 redirect 。但我更倾向于在登录界面的 action 做处理。伪代码如下:
Html代码 
<%  
String url=defaultLoginPage;  
String requestUrl= (String)session.getAttribute( “requestUrl” );  
if(requestUrl!=null ) {  
    url= requestUrl;  
}  
%>  
<form method=”post” action=”<%=url%>”>  
…  
</form>  
 
 
拦截 url 做权限判断对于 web 系统,权限表有这么几个字段:标识、名称、描述、对应 url 。
那么对于 url 请求,可以在权限表进行查找,查看该 url 是否有个对应的权限。如果有,说明该 url 需要具有没个权限才能访问,那么通过 RBAC 算法进行判断即可。如果在权限表没有找到对应记录,说明该 url 不需要进行权限验证。
 
该需求比较简单,也可以采用 Filter 机制,不妨取名 UrlAclFilter 。
 
唯一需要注意的地方是:权限表对应的 url 可能带有参数。比如 customreManager?op=add 是增加客户权限, customerManager?op=delete 是删除客户权限。
 
伪代码如下:
Java代码 
if( needPrivilegeCheck( request ) ) {  
    // 需要做权限判断  
    if( session.getAttribute( “user” ) ==null ) {  
        // 用户还没有登录,转移到登录界面  
        redirect( loginPage, request, response );  
        return;  
    } else {  
        if( userManager.hasPrivilege( user, privilegeId ) ) {  
            filter.doChain( request, response );  
            return;  
        } else {  
            redirect( forbiddenHintPage, request, response );  
            return;  
        }  
    }  
}  
 
 
基础数据库表用户信息表,保存用户信息还有密码等,有的系统会对密码进行加密保存到数据库,而不是以明文的形式保存到数据库。
 
权限表,该表基本有这么几个字段:标识、名称、描述、指向 url 、 target 。 target 表示点击该 Url 时在那个窗口显示。标识为主键。
比如下图所示 frameset ,权限菜单 target 属性应该是: MAIN角色表,该表字段:标识、名称、描述;标识为主键。
权限-角色关系表,该表有字段:角色标识、权限标识;角色标识和权限标识为复合主键。
用户-角色关系表,该表有字段:用户标识、角色标识;用户标识和角色标识为复合主键。
 
如果使用 Metadmin使用 Metadmin ,只要在 web.xml 里面,配置 LoginFilter 和 UrlAclFilter 即可。
(在 www.metadmin.com, 免费下载90天试用版)
下面就是一个示例配置,对 metadmin/demo 目录进行登录和 url 拦截权限验证,登录页面是 metadmin/demo/login.jsp 页面。
具体参数意义可查看 JAVADOC : http://www.metadmin.com/doc/javadoc/index.html LoginFilter 和 UrlAclFilter 。
 
配置示例:
Xml代码 
      <filter>  
    <filter-name>metadmin/LoginFilter</filter-name>  
    <filter-class>org.back.webFilter.LoginFilter</filter-class>  
    <init-param>  
        <param-name>loginPage</param-name>  
        <param-value>/metadmin/demo/login.jsp</param-value>  
    </init-param>  
    <init-param>  
        <param-name>uniqueFieldsParams</param-name>  
        <param-value>loginName</param-value>  
    </init-param>  
    <init-param>  
        <param-name>passwordParam</param-name>  
        <param-value>password</param-value>  
    </init-param>  
    <!--init-param>  
        <param-name>encryptMethod</param-name>  
        <param-value>shahex</param-value>  
    </init-param-->  
</filter>  
<filter>  
    <filter-name>metadmin/UrlAclFilter</filter-name>  
    <filter-class>org.back.webFilter.UrlAclFilter</filter-class>  
    <init-param>  
        <param-name>loginPage</param-name>  
        <param-value>/metadmin/demo/login.jsp</param-value>  
    </init-param>  
    <init-param>  
        <param-name>denyPage</param-name>  
        <param-value>/metadmin/demo/noPrivilege.jsp</param-value>  
    </init-param>  
</filter>  
  
     <filter-mapping>  
    <filter-name>metadmin/LoginFilter</filter-name>  
    <url-pattern>/metadmin/demo/*</url-pattern>  
</filter-mapping>  
<filter-mapping>  
    <filter-name>metadmin/UrlAclFilter</filter-name>  
    <url-pattern>/metadmin/demo/*</url-pattern>  
</filter-mapping>  
 

解决方案 »

  1.   

    spring securityhttp://family168.com/oa/springsecurity/html/
      

  2.   

    BBS格式化工具比较少,良好格式的,请查看我BLOG: http://blog.csdn.net/accessmanager88/archive/2009/06/16/4273575.aspx
      

  3.   

    在server中控制权限,在页面中携带nowUser来判断身份,或者判断是否登录
      

  4.   

    在Struts 2中,一般采用拦截器,这样对不同的包,可以采用不同的控制策略。
      

  5.   

    接分了,用acegi动态管理权限
      

  6.   

    这种控制用户会使得权限控制的逻辑很散,filter里有一部分,在services里还会有一部分。
      

  7.   

    唯一的感觉就是使用filter进行 用户权限检测、访问控制,没有新奇的地方啊,还是先看看Metadimin到底是怎么玩的