因為專注,所以專業

          我的Java Blog

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            21 隨筆 :: 30 文章 :: 6 評論 :: 0 Trackbacks

          (轉載自 http://callan.javaeye.com/blog/158392
          JAAS是對JCE安全框架的重要補充,通過提供認證用戶和確定用戶授權來增強JAVA解決方案的動態安全性,使得資源能夠得到很好得到保護和控制(JAAS使用動態的安全策略來定義權限,而不是將其靜態的嵌入到代碼中)。

          JAAS采用的是插件的運行方式,一開始就被設計成可插拔的(Pluggable),根據應用的需要,只要配置一下JAAS的配置文件,這些組件即可包含 在我們的應用程序中。使用JAAS包接口,開發者和第三方可以開發一些組件或者BEAN來實現登陸認證,或者通過與使用者或外部的系統的進行交互來訪問認 證信息(當然我們可以設計更為穩妥安全的密碼學協議)。JAAS提供了一組用于用戶鑒別的類和接口,這意味著支持JAAS的應用會要求用戶登陸,同時 JAAS提供了另一組用于用戶授權的類和接口。在討論例子之前,先對JAAS API中常用的一些類和接口做個簡單的說明。

          LoginModule :確認用戶的合法性(使用CallbackHandler或者其他類方法),并分配訪問權限principal給subject;

          LoginContext:為了實現用戶鑒別,建立相應的環境,從配置文件中導入規則;

          CallbackHandler:回調處理器,負責與用戶(代碼擁有者和執行者)交互,確認其身份的合法性;

          Subject:表示登陸處理的目標,即一個被鑒別的用戶。并可關聯一個或多個pirncipal;

          Principal:表示具有訪問權限的一個實體,可以看作是可以執行某種操作的證件。

          理解這些類和接口的關系我給個生動的比方:一個軍事學校,入學的時候校方(LoginModule)根據學生(Subject)的入學通知來確定其合法 性,這個過程交由某工作人員(CallbackHandler)執行,(CallbackHandler)確認后,(LoginModule)給不同 (Subject)根據其身份發給相關的證件(Principal),有了該證件就可以訪問對應的資源,(Subject)根據自己的 (Principal)的級別可以使用和訪問學校不同資源。

          一個(Subject)的(Principal)如果是士官級,那么可以訪問的資源就相對少些,如果是將軍級那就多些。當然一個(Subject)可以擁有多個(Principal)。

          通過分析我們會發現,JAAS采用的也是身份檢查+權限分配模式。因此JAAS的應用也分成兩個部分:(1)認證;(2)授權。過程是先認證后根據身份來授權(有歧視的嫌疑的東東,本人可是反歧視人士)。

          那么JAAS是如何實現認證的呢?又是如何實現授權的呢?且聽我慢慢分解,將其妙處展現給大家。

          二 JAAS的認證原理

          (1) 設置JAAS配置文件,關于配置非常有技巧,跟設置防火墻的過濾規則有得一拼;

          (2) 根據JAAS配置文件的條目加載一個或者多個LoginModule(通常一個,也可以變態得使用多個);

          (3) 為了管理用戶認證的有關過程,將提供一個可選的LoginModule構造函數和一個回調處理器CallbackHandler。如果沒有在構造函數中提供回調處理器,系統采用默認設置;

          (4) 初始并實例化LoginContext(加載配置規則),如果成功,則調用LoginContext的login方法。無論是否需 要,LoginContext都會去首先讀取JAAS配置文件,從中獲得要加載的登陸模塊信息,其initialize方法將按照配置文件中的相關內容提 供LoginModule運行所需要的信息;

          (5) LoginContext的login方法將調用LoginModule的login方法,確定用戶身份。該方法將設置相關的回調,并由回調處理器CallbackHandler來管理登陸處理回調;
          (6) LoginModule的login方法將負責與用戶進行交互(可能是人機交互,也可能是機機交互),如果用戶輸入信息無效,則該方 法返回FALSE,一次交互過程結束,如果用戶輸入信息有效,則該方法將設置Principal對象的Subject對象,并返回TRUE;當然 LoginModule也可以將與用戶之間的所有交互過程全部委托給處理器CallbackHandler來處理。如果登陸成功, LoginContext將調用LoginModule的commit方法將結果提交給LoginModule實例的內部狀態。


           在應用程序中使用JAAS驗證通常會涉及到以下幾個步驟:

            1. 創建一個LoginContext的實例。

            2. 為了能夠獲得和處理驗證信息,將一個CallBackHandler對象作為參數傳送給LoginContext。

            3. 通過調用LoginContext的login()方法來進行驗證。

            4. 通過使用login()方法返回的Subject對象實現一些特殊的功能(假設登錄成功)。

            下面是一個簡單的例子:

                SimpleLogin.java
                

           1package com;
           2
           3import javax.security.auth.login.LoginContext;
           4import javax.security.auth.login.LoginException;
           5
           6public class SimpleLogin {
           7    
           8    public static void main(String[] args) {
           9        
          10        // 建立登陸上下文,并通過配置文件初始化,在這里配置文件必須與程序同目錄
          11        LoginContext loginContext = null;
          12        try {
          13                                           
          14            loginContext = new LoginContext("simple"new SimpleCallbackHandle());
          15        }
           catch (LoginException e) {
          16            
          17            System.out.println(e.getMessage());
          18        }

          19        
          20        try {
          21            
          22            // 如果不拋出異常表示驗證成功
          23            loginContext.login();
          24        }
           catch (LoginException e) {
          25            
          26        }

          27    }

          28    
          29}

          30

             SimpleCallbackHandle.java 
             

           1package com;
           2
           3import java.io.BufferedReader;
           4import java.io.IOException;
           5import java.io.InputStreamReader;
           6import javax.security.auth.callback.Callback;
           7import javax.security.auth.callback.CallbackHandler;
           8import javax.security.auth.callback.NameCallback;
           9import javax.security.auth.callback.PasswordCallback;
          10import javax.security.auth.callback.UnsupportedCallbackException;
          11
          12public class SimpleCallbackHandle implements CallbackHandler {
          13
          14    public void handle(Callback[] callbacks) throws IOException,
          15            UnsupportedCallbackException {
          16
          17        for (Callback callback : callbacks) {
          18
          19            if (callback instanceof NameCallback) {
          20                NameCallback nc = (NameCallback) callback;
          21                
          22                System.out.print(nc.getPrompt());
          23                 System.out.flush();
          24                 
          25                nc.setName((new BufferedReader(new InputStreamReader(
          26                                System.in))).readLine());
          27            }
           else if (callback instanceof PasswordCallback) {
          28                PasswordCallback pcb = (PasswordCallback) callback;
          29                
          30                System.out.print(pcb.getPrompt());
          31                 System.out.flush();
          32                pcb.setPassword((new BufferedReader(new InputStreamReader(
          33                        System.in))).readLine().toCharArray());
          34            }

          35        }

          36    }

          37}

          38

          SimpleLoginModule.java

           

           1package com;
           2
           3import java.io.IOException;
           4import java.util.Map;
           5
           6import javax.security.auth.Subject;
           7import javax.security.auth.callback.Callback;
           8import javax.security.auth.callback.CallbackHandler;
           9import javax.security.auth.callback.NameCallback;
          10import javax.security.auth.callback.PasswordCallback;
          11import javax.security.auth.callback.UnsupportedCallbackException;
          12import javax.security.auth.login.LoginException;
          13import javax.security.auth.spi.LoginModule;
          14
          15public class SimpleLoginModule implements LoginModule{
          16
          17    private String userName;
          18    
          19    private char[] password;
          20    
          21    private Subject subject;
          22    
          23    private CallbackHandler callbackHandler;
          24    
          25    private Map sharedState;
          26    
          27    private Map options;
          28    
          29    private String debug;
          30    
          31    public boolean abort() throws LoginException {
          32        System.out.println("abort()");
          33        return false;
          34    }

          35
          36    public boolean commit() throws LoginException {
          37        System.out.println("commit()");
          38        return false;
          39    }

          40
          41    public void initialize(Subject subject, CallbackHandler callbackHandler,
          42            Map sharedState, Map options) {
          43        
          44        this.subject = subject;
          45        this.callbackHandler = callbackHandler;
          46        this.sharedState = sharedState;
          47        this.options = options;
          48        
          49        debug = (String)options.get("debug");
          50    }

          51
          52    public boolean login() throws LoginException {
          53        
          54        Callback[] callbacks = new Callback[2];
          55        callbacks[0= new NameCallback("用戶名: ");
          56        callbacks[1= new PasswordCallback("密碼: "false);
          57        
          58        try {
          59            
          60            callbackHandler.handle(callbacks);
          61            userName = ((NameCallback)callbacks[0]).getName();
          62            password = ((PasswordCallback)callbacks[1]).getPassword();
          63            
          64            if(debug.equals("true")){
          65                System.out.println("你輸入的用戶名為:" + userName);
          66                System.out.println("你輸入的密碼為:" + new String(password));
          67            }

          68            
          69            if(userName.equals("callan"&& new String(password).equals("callanpass")){
          70                System.out.println("驗證成功");
          71                return true;
          72            }
           else {
          73                System.out.println("驗證失敗");
          74                userName = null;
          75                password = null;
          76            }

          77        }
           catch (IOException e) {
          78            e.printStackTrace();
          79        }
           catch (UnsupportedCallbackException e) {
          80            e.printStackTrace();
          81        }

          82        
          83        return false;
          84    }

          85
          86    public boolean logout() throws LoginException {
          87        System.out.println("logout()");
          88        return false;
          89    }

          90
          91}

          92

          jaas.config

            

          將代碼編輯通過后執行以下命令:

          java -Djava.security.auth.login.config==jaas.config com.SimpleLogin


          源代碼

          posted on 2010-06-22 09:10 kevin.zhan 閱讀(309) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 友谊县| 溧阳市| 尼勒克县| 开原市| 保定市| 青海省| 巴里| 湄潭县| 贵港市| 奉节县| 平遥县| 武义县| 盈江县| 平塘县| 广宁县| 定远县| 西乌珠穆沁旗| 盘锦市| 彰化县| 山阳县| 鄂州市| 阿拉善左旗| 西城区| 宜兰县| 阳西县| 彰武县| 当阳市| 依安县| 宜章县| 北京市| 成武县| 潞城市| 雷山县| 武乡县| 寻乌县| 河源市| 平乐县| 屯昌县| 石屏县| 剑阁县| 惠来县|