基於Windows活動目錄的無線網絡Web認證

本案例是爲一箇中型規模的外包軟件公司開發的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. <% 
  9. String userkey = "XXXXXXXXXXXXXXXX";    // 替換爲你的User Key 
  10. String host = "XXX.XXX.XXX.XXX";        // AD服務器地址 
  11. String port = "389";                    // AD服務器端口 
  12. String hrsys = "http://hrsys";          // 公司內網系統首頁地址,用於認證後顯示 
  13.  
  14. //**************************************************** 
  15. // 取得接收到的傳入參數 
  16. //**************************************************** 
  17.   
  18. String pTokencode = request.getParameter("tokencode");  // 接收到的傳入參數"tokencode" 
  19. String pSrvurl = request.getParameter("srvurl");        // 接收到的傳入參數"srvurl" 
  20.   
  21.   
  22. /* 如必要,把傳入參數存放於Session對象中 */ 
  23. if(pTokencode != null
  24.     session.setAttribute("tokencode", pTokencode); 
  25. if(pSrvurl != null)  
  26.     session.setAttribute("srvurl", pSrvurl); 
  27. %> 
  28.  
  29. <html> 
  30. <head> 
  31. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"
  32. <meta http-equiv="Content-Language" content="zh"
  33. <meta http-equiv="Pragma" content="no-cache"
  34. <meta http-equiv="Cache-Control" content="no-cache"
  35. <title> 用戶認證 </title> 
  36. </head> 
  37. <body> 
  38. <center> 
  39. <br> 
  40.  
  41. <form action="" method="post"
  42.  
  43. <b>請使用公司的域賬戶進行認證</b> 
  44. <br><br> 
  45. <table bgcolor="#eefffff" border="0" cellspacing="1" cellpadding="6" width="350"
  46. <tr> 
  47. <td align="right">Domain:</td> <td><input type="text" name="domain" value="<%=request.getParameter("domain") == null ? "" : request.getParameter("domain")%>" /></td> 
  48. </tr> 
  49. <tr> 
  50. <td align="right">用戶名:</td> <td><input type="text" name="username" value="<%=request.getParameter("username") == null ? "" : request.getParameter("username")%>" /></td> 
  51. </tr> 
  52. <tr> 
  53. <td align="right">密碼:</td> <td><input type="password" name="pswd" /></td> 
  54. </tr> 
  55. </table> 
  56.  
  57.  
  58. <br> 
  59. <input type="submit" name="login" value="  登錄  " onclick="history.back();"
  60. </form> 
  61.  
  62. <%if(request.getParameter("login") != null) {  
  63. /* “登錄”按鈕按下時 */ 
  64. %> 
  65.  
  66. <table width="260" bgcolor="#888888" border="0" cellspacing="1" cellpadding="8"><tr><td bgcolor="#ffff99" align="center" valign="middle"
  67. <b> 
  68.  
  69. <% 
  70.     //**************************************************** 
  71.     // 第1步. 根據您的具體需要或業務,進行用戶登錄驗證處理 
  72.     //**************************************************** 
  73.   
  74.     boolean loginSuccess = true
  75.  
  76.     String username = request.getParameter("username"); // 用戶名 
  77.     String pswd = request.getParameter("pswd"); // 密碼 
  78.     String domain = request.getParameter("domain"); // Domain 
  79.      
  80.     /* 進行輸入參數的校驗 */ 
  81.     if(username.equals("")) { 
  82.         out.print("用戶名不可爲空!<br>"); 
  83.         loginSuccess = false
  84.     } 
  85.      
  86.     if(pswd.equals("")) { 
  87.         out.print("密碼不可爲空!<br>"); 
  88.         loginSuccess = false
  89.     } 
  90.      
  91.     if(domain.equals("")) { 
  92.         out.print("Domain不可爲空!<br>"); 
  93.         loginSuccess = false
  94.     } 
  95.      
  96.     /* 域賬戶驗證 */ 
  97.     if(loginSuccess == true) { 
  98.         String url = new String("ldap://" + host + ":" + port); 
  99.         String user = username.indexOf(domain) > 0 ? username : username +"@"+ domain; 
  100.         Hashtable<String, String> env = new Hashtable<String, String>(); 
  101.         DirContext ctx; 
  102.         env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
  103.         env.put(Context.SECURITY_PRINCIPAL, user);  
  104.         env.put(Context.SECURITY_CREDENTIALS, pswd); 
  105.         env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
  106.         env.put(Context.PROVIDER_URL, url); 
  107.  
  108.         try { 
  109.             ctx = new InitialDirContext(env); 
  110.             ctx.close(); 
  111.              
  112.             loginSuccess = true
  113.              
  114.         } catch (NamingException e) { 
  115.             //e.printStackTrace(); 
  116.             loginSuccess = false
  117.             out.print("登錄失敗!"); // 
  118.         } 
  119.     } 
  120.  
  121. %> 
  122. <br> 
  123. </b></td></tr></table> 
  124. <% 
  125.  
  126.     if(loginSuccess == true) { 
  127.    
  128.         //**************************************************** 
  129.         // 第2步. 調用Wiwiz Auth API,進行預認證 
  130.         // 重要: 請在服務器端的程序中進行此處理(例如,ASP、C#、JSP/Servet、PHP...), 
  131.         //      而不要在直接客戶端代碼中進行此處理(例如,HTML/Javascript) 
  132.         //**************************************************** 
  133.   
  134.         // 參數 "action" : 必須! 
  135.         // 設置爲"1"將使用戶認證成功 
  136.         // 設置爲"1"將使用戶認證失敗 
  137.         String action = "1"
  138.   
  139.         // 參數 "tokencode": 必須! 
  140.         // 設置與同名傳入參數相同的值 
  141.         String tokencode = (String) session.getAttribute("tokencode"); 
  142.   
  143.         // 參數 "srvurl": 必須! 
  144.         // 設置與同名傳入參數相同的值 
  145.         String srvurl = (String) session.getAttribute("srvurl"); 
  146.   
  147.         // 參數 "endtime" : 可選 
  148.         // 格式: yyyy-mm-dd hh:MM:ss  例如: 2012-05-31 21:39:00 
  149.         // 設置此參數將使用戶的Internet連接在指定時間關閉 
  150.         // 注意: 對此參數的值必須進行url編碼   
  151.         String endtime = ""//URLEncoder.encode("2012-05-31 21:39:00", "utf-8"); 
  152.   
  153.         // 參數 "postauth" : 可選 
  154.         // 例如: http://www.YourDomain.com 
  155.         // 設置此參數將設置用戶在通過認證後顯示的頁面地址 
  156.         String postauth = hrsys; 
  157.   
  158.         String parameters = 
  159.                 "wiwiz_auth_api=1&ver=1.0"// 參數 "wiwiz_auth_api" 與 "ver". 固定值 
  160.                 "&tokencode="+ tokencode +  // 參數 "tokencode". 設置方法參考上面的說明 
  161.                 "&userkey="+ userkey +      // 參數 "userkey". 設置方法參考上面的說明 
  162.                 "&action="+ action +        // 參數 "action". 設置方法參考上面的說明 
  163.                 "&endtime="+ endtime +      // 參數 "endtime". 設置方法參考上面的說明 
  164.                 "&postauth="+ postauth;     // 參數 "postauth". 設置方法參考上面的說明 
  165.   
  166.         URL u = new URL(srvurl);            // 使用傳入參數"srvurl"的值作爲請求地址 
  167.         URLConnection uc = u.openConnection(); 
  168.         uc.setDoOutput(true); 
  169.         uc.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); 
  170.         PrintWriter pw = new PrintWriter(uc.getOutputStream()); 
  171.         pw.println(parameters); 
  172.         pw.close(); 
  173.   
  174.         BufferedReader in = new BufferedReader( 
  175.         new InputStreamReader(uc.getInputStream())); 
  176.         String verifycode = in.readLine(); 
  177.         in.close(); 
  178.   
  179.         if(verifycode.startsWith("ERR")) { 
  180.             // 如果報錯,則顯示錯誤代碼 
  181.             out.println("Error: "+ verifycode); 
  182.   
  183.         } else { 
  184.             // 如沒有報錯則進行第3步。 
  185.   
  186.             //**************************************************** 
  187.             // 第3步. 調用Wiwiz Auth API,完成認證 
  188.             //****************************************************   
  189.             String redirectUrl = srvurl +       // 使用傳入參數"srvurl"的值作爲跳轉地址的前綴 
  190.                     "?wiwiz_auth_api_login=1"+  // 參數 "wiwiz_auth_api_login",固定值 
  191.                     "&tokencode="+ tokencode +  // 參數 "tokencode",設置與同名傳入參數相同的值 
  192.                     "&verifycode="+ verifycode; // 參數 "verifycode",設置與同名傳入參數相同的值 
  193.   
  194.             response.sendRedirect(redirectUrl); // 最後,進行跳轉 
  195.         } 
  196.     } 
  197. }%> 
  198.  
  199. </center> 
  200. </body> 
  201. </html> 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章