当前位置:   article > 正文

JdonJive论坛系统完整分析(3)

jive论坛
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

  3 Jive安全管理机制

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

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

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

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

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

  1 安全验证机制

  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) {//如果通过验证,保存authToken在http 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的实现。类似ForumFactory的getInstance方法

  private static void loadAuthorizationFactory() {

  …

  }

  }

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

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

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

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

  2 用户资料管理

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

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

  UserManager中无外乎用户数据的管理,如用户的创建、修改、查询和删除。DbUserManager是UserManager的一个数据库实现,可是看看DbUserManager中除了删除功能是直接通过SQL语句进行数据库删除操作外,其他都委托给User的具体实现DbUser实现的。这种实现非常类似于EJB中Session 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中,数据修改的保存是由DbUser的saveToDb方法实现的,而saveToDb方法调用是在每个setXXXX方法中。即每当外界调用DbUser的setXXXX,则表示需要改变某些字段属性值,在这个方法中直接进行数据库存储,这也类似EJB中CMP实体Bean的数据字段修改保存。

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

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

<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/884051
推荐阅读
相关标签
  

闽ICP备14008679号