Web services 安全 - HTTP Basic Authentication

Ready!發表於2016-10-29

根據 RFC2617 的規定,HTTP 有兩種標準的認證方式,即,BASIC 和 DIGEST。HTTP Basic Authentication 是指客戶端必須使用使用者名稱和密碼在一個指定的域 (Realm) 中獲取認證。

 

正如"HTTP Basic Authentication"這個名字,它是 Authentication( 認證 ) 中最簡單的方法。長期以來,這種認證方法被廣泛的使用。當你通過 HTTP 協議去訪問一個使用 Basic Authentication 保護的資源時,伺服器通常會在 HTTP 請求的 Response 中加入一個"401 需要身份驗證"的 Header,來通知客戶提供使用者憑證,以使用資源。如果你正在使用 Internet Explorer 或者 Mozilla Firefox 這樣的視覺化瀏覽器來訪問需要認證的資源,瀏覽器會彈出一個視窗,讓你輸入使用者名稱和密碼,如果所輸入的使用者名稱在資源使用者的驗證列表,並且密碼完全正確,此時,使用者才可以訪問受限的資源。

 

HTTP Basic Authentication 介紹

HTTP BASIC 認證的基本流程如圖 1 所示,

圖 1. BASIC HTTP認證基本流程

圖 1. BASIC HTTP認證基本流程

HTTP Basic Authentication 是指客戶端在使用 HTTP 協議訪問受限資源時,必須使用使用者名稱和密碼在一個指定的域 (Realm) 中獲取認證。在正式開始之前,我們需要明白以下名詞的含義:

  1. Authentication,即認證,驗證。它是一種確認的過程,通過這樣的認證過程,你可以確定某物體是不是它所聲稱的那種物體。這通常會涉及到使用者名稱和密碼,也可能是身份證明,或生物特徵,如視網膜等。
  2. Realm,即域。一個 Realm 就是一系列使用者名稱和密碼的“資料庫”,它通常用來儲存、識別某個或某些 Web 應用中有效的使用者和密碼。它還定義了每個有效使用者所對應的角色。

本文將介紹如何使用 HTTP BASIC Authentication 來保護 Web services endpoint 服務資源,當 Web services 的 Endpoints 被設定為 BASIC HTTP 認證才能訪問的受限資源時,使用者必須提供使用者名稱密碼才能使用它們,基本的流程如圖 2 所示。

圖 2. Web services 客戶端訪問受限 Web services 服務流程

圖 2. Web services 客戶端訪問受限 Web services 服務流程

 

 

為 Web Application 配置 Basic Authentication:

  1. 開啟 Tomcat 安裝目錄下的“conf”資料夾,修改檔案“tomcat-users.xml”,該檔案是用來儲存 Tomcat 預載入的使用者和角色定義的,此檔案即是上文提到的 Realm。在“<tomcat-users>”中加入如下使用者和角色:
    清單 2. 定義使用者及其角色
      <!-- Web services invoker role --> 
      <role rolename="WsInvokerRole"/> 
      
      <!-- Web services invokers/users --> 
      <user username="wsaxis" password="wsaxis" roles="WsInvokerRole"/>
  2. 開啟 Web 應用“TomcatAxis”的部署描述符:web.xml 檔案,並在“<web-app>”中加入如下片段:
    清單 3. 配置安全資源
      <!-- configurations for BASIC Authentication --> 
      <security-constraint> 
        <web-resource-collection> 
          <web-resource-name>All Web services Endpoints</web-resource-name> 
          <url-pattern>/services/*</url-pattern> 
        </web-resource-collection> 
        
        <auth-constraint> 
          <description>Web services invokers are allowed doing invocation</description> 
          <role-name>WsInvokerRole</role-name> 
        </auth-constraint> 
      </security-constraint> 
      
      <!-- authentication method --> 
      <login-config> 
        <auth-method>BASIC</auth-method> 
        <realm-name>Realm of Web services Invokers</realm-name> 
      </login-config>

    在“<security-constraint>”片段內,定義了改 Web Application 需要保護的資源,可以通過“<url-pattern>”來定義符合一定 URL 樣式的資源,上述片段的定義,保護了所有 Web services 的 endpoints。

    “<login-config>”片段定義了採取 BASIC 認證方式,其中“<realm-name>”只在 BASIC 認證方式下有效,它分配安全領域名,此名稱供瀏覽器用於對話方塊標題,且為 Authorization 頭部的一部分。

 

 

靜態呼叫類
 package sample.test.client.runable; 

 import java.net.URL; 
 import sample.test.ServiceImplServiceLocator; 
 import sample.test.ServiceImplSoapBindingStub; 

 public class StaticClientTest { 
  public static void main(String[] args) { 
    try { 
    // String userName = "wsaxis", password = "wsaxis"; 
      int addend = 64, augend = 128; 
      ServiceImplSoapBindingStub sisbs = new ServiceImplSoapBindingStub( 
          new URL(  "http://localhost:8080/TomcatAxis/services/ServiceImpl"), 
          new ServiceImplServiceLocator()); 
    // sisbs.setUsername(userName);   // sisbs.setPassword(password); 
      System.out 
          .println("Static Client Invocation:\n\tThe summation is: "
              + sisbs.sum(addend, augend)); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
 }

  

 

動態呼叫測試程式碼
 package sample.test.client.runable; 
 import javax.xml.namespace.QName; 
 import javax.xml.rpc.Call; 
 import javax.xml.rpc.ParameterMode; 
 import javax.xml.rpc.Service; 
 import javax.xml.rpc.ServiceFactory; 
 public class DynamicClientTest { 
  public static void main(String[] args) { 
    try { 
      String address = "http://localhost:8080/TomcatAxis/services/ServiceImpl"; 
      String namespaceURI = "http://test.sample"; 
      String serviceName = "ServiceImplService"; 
      String portName = "ServiceImpl"; 
      String operationName = "sum"; 
      String userName = "wsaxis", password = "wsaxis"; 
      int addend = 64, augend = 128; 
      ServiceFactory factory = ServiceFactory.newInstance(); 
      Service service = factory.createService(new QName(serviceName)); 
      Call call = service.createCall(new QName(portName)); 
      call.setTargetEndpointAddress(address); 
      QName intQName = new QName("http://www.w3.org/2001/XMLSchema","int"); 
      call.setOperationName(new QName(namespaceURI, operationName)); 
      call.addParameter("addend", intQName, ParameterMode.IN); 
      call.addParameter("augend", intQName, ParameterMode.IN); 
      call.setReturnType(intQName); 
      call.setProperty(Call.USERNAME_PROPERTY, userName); 
      call.setProperty(Call.PASSWORD_PROPERTY, password); 
      Object[] inParams = new Object[2]; 
      inParams[0] = new Integer(addend); 
      inParams[1] = new Integer(augend); 
      int value = ((Integer) call.invoke(inParams)).intValue(); 
      System.out.println("Dynamic Client Invocation:\n\tThe summation is: " + value); 
    } catch (Exception e) { 
      e.printStackTrace(); 
    } 
  } 
 }

  

 

相關文章