Posts Tagged ‘置文’

用定制标签库和配置文件实现对JSP页面元素的访问控制

星期一, 06月 2nd, 2008

控制客户端访问是开发一个基于B/Sde架构de系统de开发者必须考虑de问题.JSPSERVLET规范de基于配置文件de安全策略对资源de控制是以文件为单位de,即只可以定义某个视图全部可以或全部不能被访问.一个比较复杂de系统往往要要求对视图de一部分(如JSP页面里de一个按钮)提供访问控制,只允许被某种角色de用户访问.如果采用可编程de安全策略,因为对用户角色和操作de定义在开发时不能定义,而且这种策略加大了程序员de工作量,它可能不是一种好de办法.

我采用定制标签库和和配置文件来解决这个问题:把要权限控制deJSP页面元素如BUTTON,作为标签de内容.为受保护de内容起一个唯一de名称,把这个名称作为标签de一个属性.某个角色对某个页面元素或一组页面元素是否有权限,在XML配置文件中描述.

例如,下面deJSP页面有“详细”和“修改”两个按钮.

<%@ taglib uri=”http://mytag” prefix=”custTag” %>

<html>

<head>

<title>test</title>

</head>

<body >

<form name=”form1″ >

<table width=”600″ border=”0″ cellspacing=”0″ cellpadding=”2″ >

<tr>

<td>

<custTag:JspSecurity elementName=”employeedetail” >

<input type=”button” name=”detail” value=”详细” >

</custTag:JspSecurity>

<custTag:JspSecurity elementName=”employeemodify” >

<input type=”button” name=”modify” value=”修改” >

</custTag:JspSecurity>

</td>

</tr>

</table>

<br>

</form>

</body>

下面XML配置文件内容表示对角色为commonde用户,只对名为employeedetail de页面元素即“详细”按钮有权限,对角色为“admin”de用户,对名为employeedetail employeemodifyde页面元素即两个按钮都有权限.

<?xml version=”1.0″ encoding=”GB2312″?>

<security>

<htmlElement name=”employeedetail” >

<roleName name=”common” />

<roleName name=”admin” />

</htmlElement>

<htmlElement name=”employeemodify” >

<roleName name=”admin” />

</htmlElement>

</security>

定制标签类JspSecurityTag继承了BodyTagSupport类.BodyTagSupport有一个变量bodyContent指向起始标志和结束标志之间de内容.JspSecurityTagde私有静态变量roleList保存从XML文件中取到角色和页面元素de对应集合,私有变量ElementName对应页面元素de名称.当解析该定制标签时,首先先取到页面元素de名称,再取到当前用户de角色,如果角色有该页面元素de权限,就显示标签正文(即页面元素),否则不显示.

Pagekage com.presentation.viewhelper.JspSecurityTag;

import javax.servlet.jsp.tagext.*;

import javax.servlet.jsp.*;

import java.util.*;

import org.xml.sax.*;

import org.xml.sax.helpers.*;

import org.w3c.dom.*;

import java.io.*;

import javax.xml.parsers.*;

public class JspSecurityTag extends BodyTagSupport {

//保存从XML文件中取到角色和页面元素de对应集合

private static ArrayList roleList;

//页面元素de名称

private String elementName;

public void setElementName(String str)

{

this.elementName=str;

}

public int doAfterBody() throws JspException{

if(roleList==null)

{

roleList=getList();

}

try{

//如果认证通过就显示标签正文,否则跳过标签正文,就这么简单

if(isAuthentificated(elementName))

{

if(bodyContent != null){

JspWriter out=bodyContent.getEnclosingWriter();

bodyContent.writeOut(out);

}else

{

}

}

}catch(Exception e){

throw new JspException();

}

return SKIP_BODY;

}

//XML配置文件中取到角色和页面元素de对应,保存到静态deArrayList

private ArrayList getList()

{

DocumentBuilderFactory dbf =

DocumentBuilderFactory.newInstance();

DocumentBuilder db = null;

Document doc=null;

NodeList childlist = null;

String elementName;

String roleName;

int index;

ArrayList theList = new ArrayList();

try{

db = dbf.newDocumentBuilder();

}catch(Exception e)

{

e.printStackTrace();

}

try{

doc = db.parse(new File(”security.xml”));

}catch(Exception e)

{

e.printStackTrace();

}

//读取页面元素列表

NodeList elementList = doc.getElementsByTagName(”htmlElement”);

for(int i=0;i<elementList.getLength();i )

{

Element name = ((Element)elementList.item(i));

//页面元素de名称

elementName = name.getAttribute(”name”);

//该页面元素对应de有权限de角色de列表

NodeList rolNodeList = ((NodeList)name.getElementsByTagName(”roleName”));

for(int j=0;j<rolNodeList.getLength();j )

{

//有权限de角色de名称

//roleName = ((Element)rolNodeList.item(j)).getNodeValue();

roleName = ((Element)rolNodeList.item(j)).getAttribute(”name”);

theList.add(new ElementAndRole(elementName,roleName));

}

}

return theList;

}

//检查该角色是否有该页面元素de权限

private boolean isAuthentificated(String elementName)

{

String roleName = “”;

//在用户登陆时把该用户de角色保存到SESSION中,这里只是直接从SESSION中取用//户角色.

roleName=this.pageContext.getSession().getAttribute(”rolename”);

// roleList包含elementName属性为elementName,roleName属性为roleNamede//ElementAndRole对象,则该角色有该页面元素de权限

if(roleList.contains(new ElementAndRole(elementName,roleName)))

{

return true;

}

}

return false;

}

//表示角色和页面元素de对应de关系de内部类

class ElementAndRole{

String elementName;

String roleName;

public ElementAndRole(String elementName,String roleName)

{

this.elementName=elementName;

this.roleName=roleName;

}

public boolean equals(Object obj)

{

return(((ElementAndRole)obj).elementName.equals(this.elementName)&&((ElementAndRole)obj).roleName.equals(this.roleName));

}

}

}

在标签库能被JSP页面使用前,要做以下三个步骤

1、 JSP页面中包括一个taglib元素,确定需要加载到内存de标签库.前面deJSP文件de第一行:<%@ taglib uri=”http://mytag” prefix=”custTag” %>做de就是这件事.

2、 在配置文件web.xml中使用taglib元素确定TLD文件de位置.在web.xml中增加:

<taglib>

<taglib-uri>http://mytag</taglib-uri>

<taglib-location>

/WEB-INF/mytag.tld

</taglib-location>

</taglib>

3TLD文件必须使用taglib元素标识每个定制标签极其属性.

下面是使用这个标签库对应deTLD文件

<?xml version=”1.0″ encoding=”ISO-8859-1″ ?>

<!DOCTYPE taglib

PUBLIC “-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN”

“http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd”>

<taglib>

<tlibversion>1.0</tlibversion>

<jspversion>1.1</jspversion>

<shortname>myTag</shortname>

<uri/>

<tag>

<name>JspSecurity</name>

<tagclass>com.presentation.viewhelper.JspSecurityTag</tagclass>

<info>

JspSecurityTag

</info>

<attribute>

<name>elementName</name>

<required>true</required>

<rtexprvalue>true</rtexprvalue>

</attribute>

</tag>

</taglib>

透析PHP的配置文件php.ini

星期一, 06月 2nd, 2008

今天,我来侃侃PHP.INI文件中de一些有趣de内容吧.
  PHP.INI文件相信每位PHP爱好者都不会陌生,在PHPde上一个版本PHP3.0中它被命名为PHP3.INI.用NOTEPAD打开它,文件通常在操作系统deWindows目录下.大家都看到,PHP.INI文件里面有很多分号“”,和Windows系统一样,这些分号用来表示注解,也就是说为了配置文件清晰易懂,开发者在分号后面对每个配置功能做了简短说明,系统处理时会忽略这些注解行.当然,另外一个好处是,当PHP系统配置有变化de时候,我可以对某些行加上或去掉注解就行了,简单又方
便.
  auto_prepend_file string 可以指定一个文件自动地在读取所有php文件之前解析执行,可以为PHP、ASP、HTML等任何文件(不过图像文件可不行),在特殊时候倒是很有用.比如您想在每个PHP页面上增加一段广告,又假设您在开发一个网站,想让所有访问者在读取任何PHP页面之前进行身份验证,您就可以把您de验证相关代码作成单独文件,然后在这里设置string为该文件名就行啦.细心de读者要问了:如果我只是某些文件需要这些功能,可怎么办呀,开动脑筋吧,举个例子:
  myprefix.php文件
  <?php
  if (strstr(strtoupper( PHP_SELF),"/PHPTEST/"))
  echo "我de广告!<BR>";
  ?>
  这样只要设置:auto_prepend_file=“myprefix.php”,那么所有phptest目录下dePHP文件就都包含您de广告头啦!还需要说明de是这个文件应该放在include_path所指de路径里面,不然可能会出错de,下面就会提到它.
  auto_append_file string 和上面功能类似,只是自动加在PHP文件末尾,而且PHP程序用exit()退出时就不管用了.有了这个功能,我可以易如反掌地添加公司地址de脚注了!
  include_path string 这个参数de作用是让include()、require()等函数在这里所定义de路径中查找文件,是不是有点象DOS时代里用deSET PATH命令?这个参数可以提供一个路径列表,不过在UNIX中路径间用冒号分隔,在NT中用分号,而且斜杠de方向也不相同.如:
UNIX例:include_path=.:/home/lib
NT 例:include_path=".:c:homeib" 其中“.”表示当前目录.
gpc_order string
  GPC是GET/POST/COOKIE三种变量de第一个字母,它de顺序体现系统处理三种变量de优先级别,从左到右,优先权依次递增.默认设置为GPC,这样当有其中任两种或三种名称相同变量传递到服务器时,系统会按优先权排序,只读取优先权较高de变量.又比如设定成 “GP” 表示忽视 cookie,并在存取方法 (method) 相同时,以 POST 取代GET.当然,我在编程过程中应当尽量避免同时用不同de方式传递名称相同de变量,否则程序de可读性会变坏,而且在配置不同de系统里可能会有不同de输出结果.
  magic_quotes_gpc boolean 这个参数能确定包含在GET/POST/COOKIE这三种变量中de特殊字符:单引号、双引号、斜杠,是否加转义字符反斜杠(就是C语言里常用de“”)?因为在PHP数据库等系统中,单引号等字符通常有特殊意义,为了和真正de字符区分,我可以设置magic_quotes_gpc=on,这样如果我从用户端得到de变量中有单引号时,会在前面加转义符,然后我可以根据需要用函数stripslashes(string str);(该函数可去掉字串中de反斜杠转义符“”.若是连续二个反斜杠,则去掉一个,留下一个.若只有一个反斜杠,就直接去掉.)来去掉转义符“”,我可以比较一下:
  <form>
  <input type="Text" value="" name="a">
  <input type="Submit">
  </form>
  <?php
  echo a;
  ?>
  让我分别在magic_quotes_gpc=on和offde情况下,在文本框中输入单引号、双引号,然后提交,看看有什么区别?
  SMTP string 指定邮件发送服务器de域名或IP地址,这样我就可以发信啦,比起微软deASP来,PHPde这个功能简单方便得多了,有人要问,如果我没有配备邮件服务器怎么办?很简单,只要填上当地ISPde邮件服务器就行了.其实收发邮件服务器就像我现实生活中de邮局一样,在哪个邮局都能发信,而收信是在固定邮局.
  mysql.default_host string
  mysql.default_user string
  mysql.default_password string
  用过ODBCde读者们都知道,设置ODBCde时候总需要设置数据库所在及其默认de登录用户名和口令,这几个参数也是这个意思,不过是用在MYSQL里面罢了.为了安全起见,我还有必要在MYSQL里对该用户de权力做一些限定,千万不要偷懒用“root“啊!如果为了方便而设置了这些参数,那我就能直接用函数mysql_connect()来连接数据库了,注意这里可以不用任何参数!
  大家可能在想,虽然这样很方便,同时也很危险呀!别急,在PHPde安全模式里这些参数是无效de,下面我来看看安全模式de设置吧.
  Safe mode boolean 这可不是WINDOWS 98de安全模式啊.当PHP系统处于安全模式下时,我就能对PHP程序de行为进行一定de控制,这时候一些数据库比如MYSQL、INFOMIX等de默认数据库主机、用户名、口令等设置无效,非法用户就不能轻易连接数据库了.而且在安全模式下safe_mode_allowed_env_vars string该项设置表示什么类型de系统环境变量可以被程序更改,若设置成safe_mode_allowed_env_vars=PHP_则表示只有PHP_打头de系统环境变量可以被修改,例如这时如果在程序中企图使用putenv("windir=UUU");来修改环境变量,系统就会提示一个安全模式de保护错误.还有,安全模式对系统命令system()等有一定限制,如只能在指定目录运行等,这样能对系统文件有一定de保护作用.
  log_errors boolean 这个参数指定PHP程序出错时是否要将错误信息记录在 LOG文档中.在NT系统中如果我同时设置error_log =syslogde话,我就能在事件查看器de应用程序日志里看到PHP所发生过de错误信息,这对测试一个大型de系统有些帮助.
error_prepend_string = "<font color=ff0000>"
error_append_string = "</font>"
  这两个设置参数更有意思啦,按如上设置,那么我一眼就能看到:我de程序是否出错了!因为他de功能是把出错信息设置成显眼de红颜色了.
  至于其它de很多选项,有de一看便知,有兴趣大家自己试试吧!