Tomcat認證受權與簡單的SSO

回顧

在前幾天,我使用apache+tomcat搭建了一個集羣,有一個簡單的網站應用。Apache httpd與tomcat集羣css

今天在此基礎上,我要爲其開發一個登陸頁面,並開啓網站的認證和受權。html

基本概念

在動手以前,我須要先了解網站認證和受權的幾個基本組成部分的概念。是什麼構成了網站應用的認證和受權?java

  1. Realm - 翻譯過來叫作「域」。Realm是web容器所持有的用戶集合。不管tomcat, glassfish,jboss仍是websphere,均是符合j2ee規範或最佳實現。Realm是須要網站系統管理員進行配置的。常見的Realm有三種:數據庫,LDAP和文件系統。數據庫realm是指用戶信息都存在數據庫中,Ldap則存放在ldap中,文件系統的realm則是用戶信息按照必定的格式,存放於文件中。Realm是認證的關鍵,web容器會將用戶輸入的用戶名和密碼跟realm中的用戶信息進行比對。當比對成功的時候,認證也就成功了。node

  2. Role - 角色。 這是受權的部分。當Realm被配好之後,系統管理員能夠爲realm中的用戶分配角色。創建用戶role-mapping. 每次用戶經過web容器的認證之後,web容器會將其role信息也查詢出來,放入用戶信息中。web

  3. security-constraint。 這是web應用web.xml中的配置。 一個web應用將在web.xml中聲明其受保護的資源,並聲明某種角色能夠訪問受保護的資源。算法

  4. 認證方式。 通常認證方式分爲Basic Authentication(BA)和Form-based Authentication(FBA)。數據庫

  5. 密碼加密。一旦黑客黑了服務器,明文密碼就會所有暴露了。因此,須要對密碼進行加密存放。通常使用MD5 SHA算法對密碼進行加密。apache

以上1,2,5是由網站管理員來配置開發。3,4是由網站開發人員來配置和開發的。
c#

本實驗簡介

在前篇實驗結果的基礎上,爲網站開啓ldap認證,並製做一個login頁面。實驗所用的ldap軟件爲開源的openLDAP for windows版本。windows

OpenLDAP安裝配置

  1. 下載並安裝軟件 http://sourceforge.net/projects/openldapwindows/ OpenLDAP會被安裝成windows service.

  2. 修改slapd.conf,聲明本身的後綴和管理員. 重啓service.

    database	bdb
    suffix		"dc=mycompany,dc=com"
    rootdn		"cn=admin,dc=mycompany,dc=com"
    rootpw    admin
  3. 建立my.ldif文件,借用tomcat文檔中的案例,文件內容以下。其中定義了兩個用戶,和兩個角色。

    # Define top-level entry
    dn: dc=mycompany,dc=com
    objectClass: dcObject
    objectClass: organization
    o: mycompany
    dc:mycompany
    
    # Define an entry to contain people
    # searches for users are based on this entry
    dn: ou=people,dc=mycompany,dc=com
    objectClass: organizationalUnit
    ou: people
    
    # Define a user entry
    dn: uid=jjones,ou=people,dc=mycompany,dc=com
    objectClass: inetOrgPerson
    uid: jjones
    sn: jones
    cn: janet jones
    mail: j.jones@mycompany.com
    userPassword: janet
    
    # Define a user entry for Fred Bloggs
    dn: uid=fbloggs,ou=people,dc=mycompany,dc=com
    objectClass: inetOrgPerson
    uid: fbloggs
    sn: bloggs
    cn: fred bloggs
    mail: f.bloggs@mycompany.com
    userPassword: fred
    
    # Define an entry to contain LDAP groups
    # searches for roles are based on this entry
    dn: ou=groups,dc=mycompany,dc=com
    objectClass: organizationalUnit
    ou: groups
    
    # Define an entry for the "red" role
    dn: cn=red,ou=groups,dc=mycompany,dc=com
    objectClass: groupOfUniqueNames
    cn: red
    uniqueMember: uid=jjones,ou=people,dc=mycompany,dc=com
    uniqueMember: uid=fbloggs,ou=people,dc=mycompany,dc=com
    
    # Define an entry for the "black" role
    dn: cn=black,ou=groups,dc=mycompany,dc=com
    objectClass: groupOfUniqueNames
    cn: black
    uniqueMember: uid=fbloggs,ou=people,dc=mycompany,dc=com
  4. 運行命令 slapadd.exe -l my.ldif

  5. 驗證條目添加成功,運行查詢命令 ldapsearch.exe -x -b "dc=mycompany,dc=com" "objectClass=*"

OpenLDAP安裝配置成功,我有了下面兩個用戶:

uid\group red black
jjones Y Y
fbloggs

Y

爲Tomcat配置Realm

tomcat的realm能夠配置在server.xml中的<engine>, <host>和<context>下面。分別表示realm的做用範圍。我抱着從簡的態度,將realm配置在<engine>下面,這樣,整個tomcat上的application均可以使用此realm. 在server.xml的<engine>下面替換老的realm,添加以下代碼:

<!-- <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
	    -->
<Realm   className="org.apache.catalina.realm.JNDIRealm"
    connectionName="cn=admin,dc=mycompany,dc=com"
    connectionPassword="admin"
     connectionURL="ldap://localhost:389"
      userPassword="userPassword"
       userPattern="uid={0},ou=people,dc=mycompany,dc=com"
       <!--userRoleName="memberOf"-->
          roleBase="ou=groups,dc=mycompany,dc=com"
          roleName="cn"
        roleSearch="(uniqueMember={0})"
/>

重啓tomcat集羣。

爲Web應用配置Basic Authentication

我要爲https://www.test0.com/sessiontest/successful.jsp配置BA,只有role=red才能夠訪問此頁面。

修改web應用的web.xml,添加以下代碼:

<security-constraint>
  <web-resource-collection>
    <web-resource-name>result</web-resource-name>
    <url-pattern>/successful.jsp</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>red</role-name>
  </auth-constraint>
</security-constraint>
<login-config> 
    <auth-method>BASIC</auth-method> 
    <realm-name>tomcat</realm-name> 
</login-config>
<security-role>
  <role-name>red</role-name>
</security-role>
<security-role>
  <role-name>black</role-name>
</security-role>

而後從新打包部署sessiontest.war. 對網站進行測試,select.jsp是能夠任意訪問的,當點擊submit之後,必須對瀏覽器彈出的BA認證框輸入用戶名和密碼才能post成功。

爲Web應用配置Form-based Authentication

此次,咱們要設計一個登陸頁面。用戶能夠隨意瀏覽購物車,選擇想要的東西,但當用戶點擊submit的時候,咱們須要用戶必須登陸,才能提交訂單。因此,咱們須要對頁面https://www.test0.com/sessiontest/successful.jsp進行FBA保護。

首先設計一個登陸頁面login.html

<form action="j_security_check" method="post">
    Username<input type="text" name="j_username" /><br />
    Password<input type="password" name="j_password" /><br />
    <input type="submit" value="login" />
</form>

注意form中的action已經user和password的input的name屬性,「j_security_check","j_username"和"j_password"這些事固定的,嚴格遵循J2EE規範。將login.html放入select.jsp同級目錄下。

關於logout,我就不作設計了,很簡單,只須要執行session.invalidate(),而後跳轉到登出頁面便可。

接下來,咱們修改web.xml,配置FBA. 這裏只須要替換以前BA中的的<login-config>:

<login-config> 
    <auth-method>FORM</auth-method> 
    <form-login-config>
        <form-login-page>/login.html</form-login-page>
        <form-error-page>/login.html</form-error-page>
    </form-login-config>
</login-config>

將web應用從新打包部署。重啓tomcat。

注意:使用mod_proxy_balancer +mod_ajp+ AJP的方式鏈接tomcat,存在着一個未知錯誤。當用戶沒有登陸,訪問被保護資源的時候,按照常理,瀏覽器會顯示咱們配置好的login form。但AJP和tomcat之間的通訊會在此斷掉。這多是windows版本的問題,也多是mod_ajp和tomcat存在缺陷。總之,花了一天的時間,也沒研究出成果。google上面相似的問題挺多,惋惜都沒答案。我會開啓tomcat的log再仔細研究到底發生了什麼。

根據以往老版本,大部分使用mod_jk+ajp的方式行的通,有時間的同窗能夠嘗試mod_jk.

mod_ajp+ajp的方式只是卡在了FBA上,其它的任何資源訪問,都沒問題,爲了讓FBA工做起來,不得已,我將balancer修改爲了http模式。

<Proxy balancer://mycluster>
      BalancerMember http://127.0.0.1:8080 loadfactor=1 route=node1
      BalancerMember http://127.0.0.1:8081 loadfactor=1 route=node2
	  ProxySet stickysession=JSESSIONID
	  ProxySet lbmethod=byrequests
   </Proxy>

此外,還有一個陷阱。tomcat在作完j_security_check之後,會重定向到http,不管以前是https. 固然咱們能夠經過配置server.xml和web.xml使其重定向到Https,但通常不推薦這樣作,由於這極可能致使循環重定向。

通常的作法是在web中添加一個filter,專門負責http和https的切換。又或者在apache中配置重定向。在http-vhosts.conf中添加:

<VirtualHost *:80>
   ServerAdmin joey
   ServerName www.test0.com
   ErrorLog "logs/errlog"
   CustomLog "logs/accesslog" common
   RewriteEngine on
   RewriteRule ^/?sessiontest/(.*) https://%{SERVER_NAME}/sessiontest/$1 [R,L]
</VirtualHost>

到此,網站能夠在FBA的模式下正常運行了。

FBA的缺陷

在J2EE的規範中,FBA存在着很大的缺陷。列舉以下:

  1. login的過程沒法被幹預。咱們沒法經過添加filter的形式進行干預。login徹底交給web容器處理,頁面也是有web容器負責展現。

  2. 沒有login地址,用戶沒法bookmark一個Login頁面。直接訪問login.html是沒法提交form的。login只能在訪問受保護資源的時候纔會被觸發。

很不幸的是,tomcat徹底遵循了J2EE關於FBA的規範,這使得FBA很不實用。 WebSphere Application Server則對規範進行了變通,使得以上2個缺陷都被除去了。 Jboss, Glassfish和weblogic則不是很清楚,須要瞭解的同窗能夠去查看其文檔。

Tomcat build-in SSO

Tomcat自己集成SSO(Single Sign On)解決方案。若是一個tomcat上,部署了多個應用,這時候可使用tomcat自身的SSO解決方案。若是系統跨JVM甚至跨平臺,則須要一套複雜的SSO解決方案。複雜的SSO解決方案須要本身開發,或者使用第三方框架,如CAS, OPENSSO等。

此次的實驗,僅僅關注tomcat自帶的SSO方案。首先須要說明,tomcat自帶的SSO的必要前提是:

  1. 必須是Tomcat自帶的認證方式:BA, FBA, Degist,client-cert

  2. 必須是在同一個tomcat vhost下。

  3. 同一個JVM中。

  4. 全部的應用必須使用同一個domain。

  5. 須要cookie支持。cookie中會被插入JSESSIONIDSSO

  6. 全部應用必須使用形同的realm。

接下來,我將從新複製一份新的tomcat, 取名tomcat3. 在tomcat3\webApps下面,tomcat自帶一個web應用,叫作examples,其下/examples/jsp/security/protected/index.jsp是受FBA保護的。

修改server.xml,添加realm

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>-->
			   <Realm   className="org.apache.catalina.realm.JNDIRealm"
    connectionName="cn=admin,dc=mycompany,dc=com"
    connectionPassword="admin"
     connectionURL="ldap://localhost:389"
      userPassword="userPassword"
       userPattern="uid={0},ou=people,dc=mycompany,dc=com"
          roleBase="ou=groups,dc=mycompany,dc=com"
          roleName="cn"
        roleSearch="(uniqueMember={0})"
/>

繼續修改server.xml, 打來host下面的SSO配置:

<Valve className="org.apache.catalina.authenticator.SingleSignOn" />

而後修改examples下面的web.xml, 將受保護的資源的容許訪問角色修改爲:

<auth-constraint>
    <role-name>red</role-name>
</auth-constraint>

這樣,tomcat3下面就有一個使用OpenLDAP認證的應用examples了。接下來,我將examples複製一份,取名叫examples2,放在相同目錄下。如今tomcat3下面存在兩個應用examples和examples2,它們使用同一個realm認證。

啓動tomcat3, 訪問http://localhost:8080/examples/jsp/security/protected/index.jsp和http://localhost:8080/examples2/jsp/security/protected/index.jsp, 發現只須要登陸其中一個,另外一個再也不須要登陸。

接下來Spring Security 3

因爲FBA的缺陷,咱們須要本身製做login機制。實際上不少互聯網網站都是本身的login機制。我將藉助第三方認證工具,好比SecurityFilter或Spring來從新制做login。進階-使用Spring Security3.2搭建LDAP認證受權和Remember-me(1) 

相關文章
相關標籤/搜索