中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Java > J2EE
JdonJive论坛系统完整分析(3)
作者:佚名 时间:2005-07-23 14:42 出处:互连网 责编:chinaitpower
              摘要:Jive安全管理机制

3  Jive安全管理机制

Jive中除了前面介绍的有关设计模式实现组件外,还有其他有一定特点的组件功能,分析研究这些组件功能可以更加完整透彻地理解Jive论坛系统。

Jive安全管理机制基本是由下列部分组成:

·          安全验证机制。主要是验证用户名和密码组合是否与数据库中注册时的数据一致,以确认该用户身份为注册用户。这是对所有的JSP访问都进行拦截访问。

·          访问权限控制(ACL)。对不同的数据不同用户拥有不同的访问权限,例如,一个帖子普通用户可以浏览,但是不能更该;但是管理员却可以编辑删除。这部分功能是通过代理模式实现,为每个关键数据都建立一个代理类用来实现访问权限检查,这在前面讨论过。

·          用户资料管理系统。主要是管理用户的资料数据,进行用户组和用户关系的建立等。

安全验证机制

Jive的安全验证机制是按照比较通用的思路设计的。类似前面“简单的用户注册管理系统”中的介绍,Jive也是在所有的JSP页面中include一个安全检验功能的global.jsp。由于global.jsp是在每个JSP一开始必须执行的功能,因此通过拦截global.jsp拦截发往各个JSP页面的请求(request)。如果这个请求是合法的,将被允许通过;如果不是,将注明请求者身份是Anonymous(匿名者)。

global.jsp代码如下:

boolean isGuest = false;

Authorization authToken = SkinUtils.getUserAuthorization(request, response);

if (authToken == null) {//未被验证通过

    authToken = AuthorizationFactory.getAnonymousAuthorization();

    isGuest=true;

}

Jive中,以Authorization对象作为验证通过的标志,它的接口代码如下:

public interface Authorization {

    public long getUserID();   

    public boolean isAnonymous();

}

具体实现是DbAuthorization,代码如下:

public final class DbAuthorization implements Authorization, Serializable {

    private long userID;

    protected DbAuthorization(long userID) {

        this.userID = userID;

    }

    public long getUserID() {

        return userID;

    }

    public boolean isAnonymous() {

        return userID == -1;

    }

}

此类只是一个userID,因此只是一个象征性的标志。

SkinUtils是一个为JSP服务的类,它的getUserAuthorization代码如下:

public static Authorization getUserAuthorization

        (HttpServletRequest request, HttpServletResponse response)

  {

    HttpSession session = request.getSession();

    // HttpSession中获取Authorization实例

    Authorization authToken =

(Authorization)session.getAttribute(JIVE_AUTH_TOKEN);

    if (authToken != null) {     return authToken;  }

 

    // 如果HttpSession中没有,检查用户浏览器cookie

    Cookie cookie = getCookie(request, JIVE_AUTOLOGIN_COOKIE);

    if (cookie != null) {

        try {

           String[] values = decodePasswordCookie(cookie.getValue());

           String username = values[0];

           String password = values[1];

           //cookie中获得用户名和密码后,进行安全验证

           authToken = AuthorizationFactory.getAuthorization(username,password);

        }catch (Exception e) {}

        // put that token in the user's session:

        if (authToken != null) {//如果通过验证,保存authTokenhttp Session

           session.setAttribute(JIVE_AUTH_TOKEN, authToken);

        }

       // return the authorization token

        return authToken;

    }

    return null;

}

用户验证预先通过两个步骤。首先检查HttpSession中是否保存了该用户的验证信息,如果用户第一次验证通过,反复访问,这道关口检查就可以通过。

如果HttpSession中没有验证信息,那么从该用户的浏览器cookie中寻找用户名和密码。如果该用户激活了cookie保存这些登录信息,那么应该可以找到用户名和密码,这样就省却了用户再次从键盘输入用户名和密码,将用户名和密码通过下列语句进行数据库验证:

authToken = AuthorizationFactory.getAuthorization(username,password);

这一举是验证关键。AuthorizationFactory是一个抽象类,定义了Jive安全验证机制所需的所有方法,AuthorizationFactory的实现类似前面讨论的ForumFactory实现,是使用工厂模式加动态类反射机制完成的,代码如下:

public abstract class AuthorizationFactory {

   //定义一个数据库具体实现

    private static String className =

        " com.Yasna.forum.database.DbAuthorizationFactory";

 

    private static AuthorizationFactory factory = null;

    //验证方法 如果没有UnauthorizedException抛出,表示验证通过

    public static Authorization getAuthorization(String username,

            String password) throws UnauthorizedException

    {

        loadAuthorizationFactory();

        return factory.createAuthorization(username, password);

    }

    //匿名者处理方法

    public static Authorization getAnonymousAuthorization() {

        loadAuthorizationFactory();

        return factory.createAnonymousAuthorization();

    }

    //需要具体实现的抽象方法

    protected abstract Authorization createAuthorization(String username,

            String password) throws UnauthorizedException;

    protected abstract Authorization createAnonymousAuthorization();

    //动态配置AuthorizationFactory的具体实现,可以在配置文件中定义一个

    //基于LDAP的实现。类似ForumFactorygetInstance方法

    private static void loadAuthorizationFactory() {

        …

    }

}

AuthorizationFactory看上去很复杂,实际只有一个核心方法getAuthorization。实现用户名和密码的验证。如果无法通过验证,有两个信息实现显示:一个是抛出UnauthorizedException,另外一个是返回空的Authorization对象。

那么,子类DbAuthorizationFactory毫无疑问就是查询数据库,将输入的用户名和密码与数据库保存的用户名和密码进行校验。

Jive的安全验证机制比较简单易懂,值得在实践中学习借鉴。但是注意到这套安全验证机制只是Web层的“手工”验证,资源访问权限(ACL)也是自己“手工”来实现的。如果使用EJB技术,因为EJB容器本身有一定的资源访问控制体系,因此在Web层验证通过后,需要将这些登录信息传递到EJB层。当然如果直接使用Web容器的安全验证机制,那么Web层与EJB层之间的登录信息传递将由容器实现,这样就更加简单方便。

Jive这种的安全验证并不是使用Web容器的安全验证机制,如何使用Web容器的安全验证机制将在以后章节介绍。尽管如此,Jive这套安全验证机制对付小型系统的应用也是足够的。


用户资料管理

Jive中,用户User对象的操作访问类似于论坛Forum对象的访问,与User对象有关的操作都封装在一个类中操作,这是外观(Facade)模式的应用。

Jive中,用户资料管理属于大系统中的一个子系统,在这个子系统中,用户子系统和其他系统又有一定的关系,涉及的类不少,通过建立一个UserManager类来统一对外接口,使得整个子系统条目结构清晰。

UserManager中无外乎用户数据的管理,如用户的创建、修改、查询和删除。DbUserManagerUserManager的一个数据库实现,可是看看DbUserManager中除了删除功能是直接通过SQL语句进行数据库删除操作外,其他都委托给User的具体实现DbUser实现的。这种实现非常类似于EJBSession Bean和实体Bean之间的关系。以创建用户资料为例,代码如下:

public User createUser(String username, String password, String email)

            throws UserAlreadyExistsException

 {

        User newUser = null;

        try {

            //username查询改用户是否存在

            User existingUser = getUser(username);

            //如果没有抛出UserNotFoundException异常,表示该用户存在

            //The user already exists since now exception, so:

            throw new UserAlreadyExistsException();

        } catch (UserNotFoundException unfe) {

            //该用户不存在,创建一个新用户

            newUser = new DbUser(username, password, email, factory);

        }

        return newUser;

}

DbUser的构造方法实际是用户资料的新增创建:

protected DbUser(String username, String password, String email,

            DbForumFactory factory)

{

        this.id = SequenceManager.nextID(JiveGlobals.USER);  //获得自增ID

        this.username = username;

        // Compute hash of password.

        this.passwordHash = StringUtils.hash(password);  //获得加密的密码

        this.email = email;

        this.factory = factory;

        long now = System.currentTimeMillis();

        creationDate = new java.util.Date(now);

        modifiedDate = new java.util.Date(now);

        properties = new Hashtable();

        insertIntoDb();              //数据库插入数据

}

Jive中,数据修改的保存是由DbUsersaveToDb方法实现的,而saveToDb方法调用是在每个setXXXX方法中。即每当外界调用DbUsersetXXXX,则表示需要改变某些字段属性值,在这个方法中直接进行数据库存储,这也类似EJBCMP实体Bean的数据字段修改保存。

Jive中组Group与用户User处理几乎差不多,只是在Group中整合了权限方面的信息,这种做法是有一定的局限性,不是很值得借鉴,要想设计一个动态扩展灵活的权限系统,必须在用户或组与权限之间引入角色概念,也就是比较先进的基于角色的权限系统(RBAC Roled-Based Access Control,相关网址:http://csrc.nist.gov/rbac/)。

RBAC中,用户组只是用户的一个集合,应该是通过角色和权限发生联系。所以RBAC认为,如果给用户组赋予权限,那么用户组也接近角色的概念。

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有