设为首页 收藏本站
查看: 604|回复: 0

[经验分享] 源码提供 —— 使用Apache Commons HttpClient灵活实现JAAS签权

[复制链接]

尚未签到

发表于 2017-1-14 11:25:25 | 显示全部楼层 |阅读模式
JavaEE提供了JAAS安全机制,在架构一个web系统时,可以根据这个标准来保护系统的安全。

先对JAAS标准作个简单介绍,JAAS为Java企业应用提供了安全规范和接口,规范主要由JavaEE服务器实现,接口则面向服务实现以及应用开发。一个安全的web系统,必须对其访问用户进行访问范围的控制,在JAAS中,这种控制体现在用户的角色上。举个例子,假设一个web系统(假设为http://www.asys.com)有两个受保护的url资源分别为Area-1(http://www.asys.com/areaone)和Area-2(http://www.asys.com/areatwo),系统中有两种角色Role1和Role2,根据约定,只有属于Role1的用户才能访问Area-1,另外只有拥有Role2角色的用户才能访问Area-2,如何实现呢?很简单,根据JAAS标准,可以通过在一个JavaEE服务器中进行相应的配置来实现声明式的JAAS安全。以tomcat5.0为例,首先,在conf/tomcat-users.xml这个文件,你可以定义用户信息和角色对应关系:
xml 代码
 

  • xml version='1.0' encoding='utf-8'?>  
  • <tomcat-users>  
  •   <role rolename="Role1"/>  
  •   <role rolename="Role2"/>  
  •    <user username="user1" password="123" roles="Role1"/>  
  •   <user username="user2" password="456" roles="Role2"/>  
  • <!---->tomcat-users>  


以上设置相当于定义了安全机制依赖的用户角色元数据,那么接下来就是将角色与受保护的资源进行关联声明设置,这一步需要在你具体的web应用程序的部署文件web.xml(也可以是其他部署文件比如ejb描述文件)中进行:
xml 代码
 

  • xml version="1.0" encoding="UTF-8"?>  
  • <web-app version="2.4"   
  •     xmlns="http://java.sun.com/xml/ns/j2ee"   
  •     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  •     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   
  •     http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
  •       
  •   <login-config>  
  •     <auth-method>FORM<!---->auth-method>  
  •     <form-login-config>  
  •         <form-login-page>/login.jsp<!---->form-login-page>  
  •         <form-error-page>/error.jsp<!---->form-error-page>  
  •     <!---->form-login-config>  
  •   <!---->login-config>  
  •     
  •   <security-constraint>  
  •     <web-resource-collection>  
  •         <web-resource-name>Area-1<!---->web-resource-name>  
  •         <url-pattern>/areaone<!---->url-pattern>  
  •     <!---->web-resource-collection>  
  •     <auth-constraint>  
  •         <role-name>Role1<!---->role-name>  
  •     <!---->auth-constraint>  
  •   <!---->security-constraint>  
  •     
  •   <security-constraint>  
  •     <web-resource-collection>  
  •         <web-resource-name>Area-2<!---->web-resource-name>  
  •         <url-pattern>/areatwo<!---->url-pattern>  
  •     <!---->web-resource-collection>  
  •     <auth-constraint>  
  •         <role-name>Role2<!---->role-name>  
  •     <!---->auth-constraint>  
  •   <!---->security-constraint>  
  •   
  •   <security-role>  
  •     <role-name>Role1<!---->role-name>  
  •   <!---->security-role>  
  •   
  •   <security-role>  
  •     <role-name>Role2<!---->role-name>  
  •   <!---->security-role>  
  •   
  • <!---->web-app>  


由于xml有很好的自我描述性,上面的信息意义比较明确,如果看过前面的假设案例,再具体琢磨一下应该明白,在这里就不过多解释。不过需要交待的是这个<login-config><login-config>标签,这个用途就是指定登陆签权的方式,根据JAAS标准,有BASIC/FORM/DIGEST等几种登陆方式,BASIC估计很多人在访问一些网站时碰到过,浏览器中打开一个登陆窗口,需要输入用户名密码才能访问某个资源,这种方式非常简单,是真正意义上的“声明式安全”,根本不需要编写任何代码,但是安全性和灵活性较差,这里姑且先不讨论BASIC和DIGEST模式,只讨论用得非常多的FORM模式,这种模式就是用html表单来提交用户名和密码,优点是灵活,比如你可以把登陆界面搞得更为花哨,但是有一点也比较讨厌的是,根据JAAS标准,这个登陆表单的提交Action必须是"action=/j_security_check",另外用户名密码参数名必须是j_username和j_password,为什么说它讨厌,就是你想搞得自我一些是没辙了,比如你要先通过自己的action,做一些业务逻辑或者往数据库写些什么,对不起没门,你只能提交到/j_security_check这个 url,而且,服务器验证通过后,它会自动转向你想访问的受保护资源,当然你可以通过filter来实现后置的登陆处理,但是这种方式也有问题,比如,你想加个验证码机制,用户除了输入用户名密码外,还要输对验证码才能登陆,那就无法用后置处理加以实现了。到这里你可能会咒骂,“这个JAAS是什么个标准?!居然如此不灵活!“,解决这个问题可以通过服务器端的response.sendRedirect来实现自定义登陆操作验证再执行 j_security_check,但这有个毛病是用户名密码再来回一次浏览器和服务器,安全性和效率都不好,在本文中,老黄博客用一种不同的方式,就是在服务器端通过httpclient代替用户端的浏览器来执行j_security_check操作,这样就解决了这个矛盾,你想前置或者后置进行 j_security_check检查都可以,并且完全提供开源源代码,:)

具体思路是这样的,在服务器端获取到用户名、密码、sessionid、并生成j_security_check的完整url路径,调用 JSecurityCheckHelper这个对象的doCheck方法就可以完成签权,同时JSecurityCheckHelper还支持SSL和服务代理(这可是花了老黄近一个月的心血啊)。JSecurityCheckHelper的代码骨架如下:

java 代码

  • package laohuang.helper.jaas;  
  •   
  • /** 
  •  * <code>JSecurityCheckHelper</code>利用HttpClient实现JAAS签权。 
  •  *  
  •  * @author newman.huang 
  •  * @version 1.0 2007/2/26 
  •  */  
  • public class JSecurityCheckHelper {  
  •       
  •     private HttpClient httpClient;  
  •       
  •     static{  
  •         loadProxyConfig();  
  •         registerHttps();  
  •     }  
  •           
  •     //加载代理属性  
  •     private static void loadProxyConfig(){  
  •         ...  
  •     }  
  •       
  •     //注册https协议以支持HttpClient通过SSL通讯  
  •     @SuppressWarnings("deprecation")  
  •     private static void registerHttps(){  
  •         ...  
  •     }  
  •       
  •     /** 
  •      * 构建。 
  •      * 
  •      */  
  •     public JSecurityCheckHelper(){  
  •         ...  
  •     }  
  •       
  •     /** 
  •      * 执行j_security_check。 
  •      */  
  •     public String doCheck(String userName, String password,  
  •         String jSessionId, String jSecCheckFullURL) throws SecurityCheckException {  
  •           
  •         ...  
  •     }  
  •       
  •     //设置代理以通过代理执行j_security_check校验  
  •     private void setProxy(){  
  •         ...  
  •     }  
  •       
  •     //生成HttpClient Cookie  
  •     private Cookie genRequestCookie(String jSessionId,String fullURL){  
  •         ...  
  •     }  
  •       
  •     //通过url获取cookie的域名  
  •     private static String parseCookieDomainName(String url){  
  •         ...  
  •     }  
  •       
  •     //辅助方法,执行一个get请求,仅供测试使用  
  •     private void doGetRequest(String url){  
  •         ...  
  •     }  
  •       
  •     //辅助方法,获取当前JSESSIONID,仅供测试使用  
  •     private String getJSessionId(){  
  •         ...  
  •     }  
  •       
  •     ...  
  • }  


本实现可以解决j_security_check Form验证的不灵活弊端,也可以将代码集成到有需要的客户端测试当中,另外,可以充当学习HttpClient的范例代码。正如硬币都有正反两面,这个解决方案没有遵循server/Client分离的实现原则,如果放置在服务器端,在不同的应用环境下,需要处理的细节过多,比如需要关注传输协议细节(SSL),是否使用代理等等,尽管如此,</login-config></login-config>JSecurityCheckHelper还是都为你提供了这些实现。
<login-config><login-config>
</login-config></login-config>

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-328310-1-1.html 上篇帖子: java 发邮件 用org.apache.commons.mail (jar包为commons-email-1.2.jar,mail.jar) 下篇帖子: Windows环境下 基于 Apache 的SVN 服务器 安装及配置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表