ubnt解决方案
查看: 6872|回复: 24

[无线覆盖] 基于Windows活动目录的无线网络Web认证

[复制链接]

774

回帖

6099

积分

1305 小时

在线时间

中校

技术达人

注册时间
2011-4-12
金币
4969 个
威望
21 个
荣誉
3 个
累计签到:32 天
连续签到:0 天
[LV.50]初入江湖
发表于 2012-6-22 17:16 |显示全部楼层
本帖最后由 tiida2011 于 2012-6-23 15:07 编辑
本案例是为一个中型规模的外包软件公司开发的WiFi网页认证系统。

整个公司的网络都是采用典型的Windows活动目录(Active Directory)进行管理,所有员工都分配有各自的域账户。员工的计算机都是有线连接,因为主要做的是外包项目,信息安全方面要求很严格,所以公司规定一般的员工不能上网。
现在公司希望在每一层都能为员工提供无线WiFi上网的方式(非办公用),但是也需要用域账户进行认证,而且要用Web认证(可以防止WiFi万能钥匙这类手机软件)。

我们采用的方式非常简单,即,在每一层都安装一个无线路由器,WAN口接入公司网络(非办公用网段)并连接外网。无线路由器统一刷DD-WRT,安装Wiwiz客户端。

然后在公司内网的Java服务器中增加一个我们写的JSP页面,用于Web认证。
重点就在这个JSP页面程序,这里简要说明一下。
这个JSP页面程序接收来自无线网络用户提交的域名、用户名和密码,然后连接域控制器,进行域账户的验证,如果出错则报错。如果域账户验证通过,则调用Wiwiz Auth API使之完成Web认证。认证通过后,浏览器将自动显示公司内网主页。

简易版的效果图如下:


以下是Web认证页面的JSP程序源码:
  1. <%@ page contentType="text/html;charset=UTF-8" %>
  2. <%@ page import="java.io.*"%>
  3. <%@ page import="java.util.*"%>
  4. <%@ page import="java.net.*"%>
  5. <%@ page import="javax.naming.*"%>
  6. <%@ page import="javax.naming.directory.*"%>

  7. <%
  8. String userkey = "XXXXXXXXXXXXXXXX";        // 替换为你的User Key
  9. String host = "XXX.XXX.XXX.XXX";                 // AD服务器地址
  10. String port = "389";                                         // AD服务器端口
  11. String hrsys = "http://hrsys";                        // 公司内网系统首页地址,用于认证后显示

  12. //****************************************************
  13. // 取得接收到的传入参数
  14. //****************************************************

  15. String pTokencode = request.getParameter("tokencode");        // 接收到的传入参数"tokencode"
  16. String pSrvurl = request.getParameter("srvurl");                // 接收到的传入参数"srvurl"


  17. /* 如必要,把传入参数存放于Session对象中 */
  18. if(pTokencode != null)
  19.         session.setAttribute("tokencode", pTokencode);
  20. if(pSrvurl != null)        
  21.         session.setAttribute("srvurl", pSrvurl);
  22. %>

  23. <html>
  24. <head>
  25. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  26. <meta http-equiv="Content-Language" content="zh">
  27. <meta http-equiv="Pragma" content="no-cache">
  28. <meta http-equiv="Cache-Control" content="no-cache">
  29. <title> 用户认证 </title>
  30. </head>
  31. <body>
  32. <center>
  33. <br>

  34. <form action="" method="post">

  35. <b>请使用公司的域账户进行认证</b>
  36. <br><br>
  37. <table bgcolor="#eefffff" border="0" cellspacing="1" cellpadding="6" width="350">
  38. <tr>
  39. <td align="right">Domain:</td> <td><input type="text" name="domain" value="<%=request.getParameter("domain") == null ? "" : request.getParameter("domain")%>" /></td>
  40. </tr>
  41. <tr>
  42. <td align="right">用户名:</td> <td><input type="text" name="username" value="<%=request.getParameter("username") == null ? "" : request.getParameter("username")%>" /></td>
  43. </tr>
  44. <tr>
  45. <td align="right">密码:</td> <td><input type="password" name="pswd" /></td>
  46. </tr>
  47. </table>


  48. <br>
  49. <input type="submit" name="login" value="  登录  " onclick="history.back();">
  50. </form>

  51. <%if(request.getParameter("login") != null) {
  52. /* “登录”按钮按下时 */
  53. %>

  54. <table width="260" bgcolor="#888888" border="0" cellspacing="1" cellpadding="8"><tr><td bgcolor="#ffff99" align="center" valign="middle">
  55. <b>

  56. <%
  57.         //****************************************************
  58.         // 第1步. 根据您的具体需要或业务,进行用户登录验证处理
  59.         //****************************************************

  60.         boolean loginSuccess = true;

  61.         String username = request.getParameter("username"); // 用户名
  62.         String pswd = request.getParameter("pswd"); // 密码
  63.         String domain = request.getParameter("domain"); // Domain
  64.         
  65.         /* 进行输入参数的校验 */
  66.         if(username.equals("")) {
  67.                 out.print("用户名不可为空!<br>");
  68.                 loginSuccess = false;
  69.         }
  70.         
  71.         if(pswd.equals("")) {
  72.                 out.print("密码不可为空!<br>");
  73.                 loginSuccess = false;
  74.         }
  75.         
  76.         if(domain.equals("")) {
  77.                 out.print("Domain不可为空!<br>");
  78.                 loginSuccess = false;
  79.         }
  80.         
  81.         /* 域账户验证 */
  82.         if(loginSuccess == true) {
  83.                 String url = new String("ldap://" + host + ":" + port);
  84.                 String user = username.indexOf(domain) > 0 ? username : username +"@"+ domain;
  85.                 Hashtable<String, String> env = new Hashtable<String, String>();
  86.                 DirContext ctx;
  87.                 env.put(Context.SECURITY_AUTHENTICATION, "simple");
  88.                 env.put(Context.SECURITY_PRINCIPAL, user);
  89.                 env.put(Context.SECURITY_CREDENTIALS, pswd);
  90.                 env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
  91.                 env.put(Context.PROVIDER_URL, url);

  92.                 try {
  93.                         ctx = new InitialDirContext(env);
  94.                         ctx.close();
  95.                         
  96.                         loginSuccess = true;
  97.                         
  98.                 } catch (NamingException e) {
  99.                         //e.printStackTrace();
  100.                         loginSuccess = false;
  101.                         out.print("登录失败!");        //
  102.                 }
  103.         }

  104. %>
  105. <br>
  106. </b></td></tr></table>
  107. <%

  108.         if(loginSuccess == true) {
  109.   
  110.                 //****************************************************
  111.                 // 第2步. 调用Wiwiz Auth API,进行预认证
  112.                 // 重要: 请在服务器端的程序中进行此处理(例如,ASP、C#、JSP/Servet、PHP...),
  113.                 //      而不要在直接客户端代码中进行此处理(例如,HTML/Javascript)
  114.                 //****************************************************

  115.                 // 参数 "action" : 必须!
  116.                 // 设置为"1"将使用户认证成功
  117.                 // 设置为"1"将使用户认证失败
  118.                 String action = "1";

  119.                 // 参数 "tokencode": 必须!
  120.                 // 设置与同名传入参数相同的值
  121.                 String tokencode = (String) session.getAttribute("tokencode");

  122.                 // 参数 "srvurl": 必须!
  123.                 // 设置与同名传入参数相同的值
  124.                 String srvurl = (String) session.getAttribute("srvurl");

  125.                 // 参数 "endtime" : 可选
  126.                 // 格式: yyyy-mm-dd hh:MM:ss  例如: 2012-05-31 21:39:00
  127.                 // 设置此参数将使用户的Internet连接在指定时间关闭
  128.                 // 注意: 对此参数的值必须进行url编码  
  129.                 String endtime = ""; //URLEncoder.encode("2012-05-31 21:39:00", "utf-8");

  130.                 // 参数 "postauth" : 可选
  131.                 // 例如: http://www.YourDomain.com
  132.                 // 设置此参数将设置用户在通过认证后显示的页面地址
  133.                 String postauth = hrsys;

  134.                 String parameters =
  135.                                 "wiwiz_auth_api=1&ver=1.0"+ // 参数 "wiwiz_auth_api" 与 "ver". 固定值
  136.                                 "&tokencode="+ tokencode +        // 参数 "tokencode". 设置方法参考上面的说明
  137.                                 "&userkey="+ userkey +                // 参数 "userkey". 设置方法参考上面的说明
  138.                                 "&action="+ action +                // 参数 "action". 设置方法参考上面的说明
  139.                                 "&endtime="+ endtime +                // 参数 "endtime". 设置方法参考上面的说明
  140.                                 "&postauth="+ postauth;         // 参数 "postauth". 设置方法参考上面的说明

  141.                 URL u = new URL(srvurl);                        // 使用传入参数"srvurl"的值作为请求地址
  142.                 URLConnection uc = u.openConnection();
  143.                 uc.setDoOutput(true);
  144.                 uc.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
  145.                 PrintWriter pw = new PrintWriter(uc.getOutputStream());
  146.                 pw.println(parameters);
  147.                 pw.close();

  148.                 BufferedReader in = new BufferedReader(
  149.                 new InputStreamReader(uc.getInputStream()));
  150.                 String verifycode = in.readLine();
  151.                 in.close();

  152.                 if(verifycode.startsWith("ERR")) {
  153.                         // 如果报错,则显示错误代码
  154.                         out.println("Error: "+ verifycode);

  155.                 } else {
  156.                         // 如没有报错则进行第3步。

  157.                         //****************************************************
  158.                         // 第3步. 调用Wiwiz Auth API,完成认证
  159.                         //****************************************************        
  160.                         String redirectUrl = srvurl +                // 使用传入参数"srvurl"的值作为跳转地址的前缀
  161.                                         "?wiwiz_auth_api_login=1"+        // 参数 "wiwiz_auth_api_login",固定值
  162.                                         "&tokencode="+ tokencode +        // 参数 "tokencode",设置与同名传入参数相同的值
  163.                                         "&verifycode="+ verifycode;        // 参数 "verifycode",设置与同名传入参数相同的值

  164.                         response.sendRedirect(redirectUrl);        // 最后,进行跳转
  165.                 }
  166.         }
  167. }%>

  168. </center>
  169. </body>
  170. </html>
复制代码




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册 微信登录

x

点评

很好,很不错!  发表于 2012-7-1 02:12

评分

2

查看全部评分

717

回帖

3840

积分

237 小时

在线时间

高级工程师

注册时间
2011-2-8
金币
2536 个
威望
106 个
荣誉
0 个
累计签到:182 天
连续签到:0 天
[LV.200]无线新星
发表于 2012-6-22 17:53 |显示全部楼层
能不能出一个详细的教程。
回复

使用道具 举报

98

回帖

247

积分

20 小时

在线时间

少尉

注册时间
2012-5-15
金币
143 个
威望
0 个
荣誉
0 个
累计签到:6 天
连续签到:0 天
[LV.20]漫游旅程
发表于 2012-6-22 18:59 |显示全部楼层
楼主在写详细点 我想学学 ..
回复

使用道具 举报

160

回帖

788

积分

139 小时

在线时间

中尉

注册时间
2011-11-26
金币
597 个
威望
1 个
荣誉
0 个
累计签到:1 天
连续签到:0 天
[LV.20]漫游旅程
发表于 2012-6-22 22:20 |显示全部楼层
楼主在写详细点 我想学学 ..
回复

使用道具 举报

1731

回帖

2881

积分

88 小时

在线时间

少校

注册时间
2012-1-27
金币
1099 个
威望
8 个
荣誉
0 个
累计签到:178 天
连续签到:0 天
[LV.200]无线新星
发表于 2012-6-22 22:29 |显示全部楼层
:o:o
回复

使用道具 举报

3

回帖

11

积分

1 小时

在线时间

新兵上阵

注册时间
2012-6-18
金币
8 个
威望
0 个
荣誉
0 个

尚未签到

发表于 2012-6-23 19:40 |显示全部楼层
望楼主给详细的教程!!!小弟不胜感激!!
回复

使用道具 举报

568

回帖

1298

积分

266 小时

在线时间

上尉

注册时间
2012-6-14
金币
648 个
威望
0 个
荣誉
0 个

尚未签到

发表于 2012-6-24 08:41 |显示全部楼层
楼主能说清楚点怎么使用吗?需要单独安装api吗(完全不懂这货)。。。还是直接放服务器就能用了。。?
回复

使用道具 举报

774

回帖

6099

积分

1305 小时

在线时间

中校

技术达人

注册时间
2011-4-12
金币
4969 个
威望
21 个
荣誉
3 个
累计签到:32 天
连续签到:0 天
[LV.50]初入江湖
发表于 2012-6-25 16:39 |显示全部楼层
aiyundetianshi 发表于 2012-6-22 17:53
能不能出一个详细的教程。

哪里不够详细呢?
回复

使用道具 举报

124

回帖

958

积分

112 小时

在线时间

中尉

注册时间
2011-3-25
金币
799 个
威望
1 个
荣誉
0 个
累计签到:16 天
连续签到:0 天
[LV.20]漫游旅程
发表于 2012-6-26 11:36 |显示全部楼层
很牛的方案呀。楼主这一单赚的不少吧?
回复

使用道具 举报

124

回帖

1072

积分

124 小时

在线时间

上尉

注册时间
2010-12-22
金币
902 个
威望
3 个
荣誉
0 个

尚未签到

发表于 2012-6-27 14:55 |显示全部楼层
已经很详细了
回复

使用道具 举报

774

回帖

6099

积分

1305 小时

在线时间

中校

技术达人

注册时间
2011-4-12
金币
4969 个
威望
21 个
荣誉
3 个
累计签到:32 天
连续签到:0 天
[LV.50]初入江湖
发表于 2012-6-28 21:01 |显示全部楼层
梦已欠费$ 发表于 2012-6-22 18:59
楼主在写详细点 我想学学 ..

你觉得那里还需要再详细点呢?
回复

使用道具 举报

1302

回帖

1万

积分

1138 小时

在线时间

上校

注册时间
2009-4-6
金币
11659 个
威望
10 个
荣誉
7 个
累计签到:1070 天
连续签到:0 天
[LV.1095]铁杆粉丝
发表于 2012-6-29 12:16 |显示全部楼层
支持。收藏了,有时间好好学习下。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册 微信登录

本版积分规则

站点统计 | Archiver | 手机版 | 无线门户 ( 粤ICP备11076993号|粤公网安备44010602008359号 ) |网站地图

GMT+8, 2024-5-3 18:25

返回顶部 返回列表