<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 156,  comments - 601,  trackbacks - 0
    注:例子的原作者是 Paul Feuer和John Musser,我在上面加入些注釋以便更好的理解Jaas的實現
    首先,我們來看一下 JAAS 一個認證操作的實現流程

    先看一下這個認證操作會使用的接口如下:

    javax.security.auth.callback.CallbackHandler
    javax.security.auth.spi.LoginModule

    下面看一下這個基于JAAS認證的實現流程:
    JaasTest 實現一個登錄的請求操作:
     1 public class JaasTest {
     2 
     3     public static void main(String[] args) {
     4 
     5         boolean loginSuccess = false;
     6         Subject subject = null;
     7 
     8         try {
     9                 // ConsoleCallbackHandler 實現CallbackHandler接口 處理用戶名和密碼(這里從鍵盤輸入)
    10             ConsoleCallbackHandler cbh = new ConsoleCallbackHandler();
    11                         // 啟動LoginContext, 裝載LoginModule 
    12                         //login module配置文件,通過java -Djava.security.auth.login.config=jaas.config指定
    13                         //其中 example就是module名字
    14             LoginContext lc = new LoginContext("Example", cbh);
    15 
    16             try {
    17                 lc.login(); //進行登錄,它會回調 CallbackHandler的handle方法,要求
    18                 //handle方法把傳入的參數Callback[]中找到NameCallback類型,調用NameCallback.setName把
    19                 //用戶名傳進去,找到PasswordCallback類型,調用PasswordCallback.setPassword方法把密碼傳進去
    20                 //如果登錄失敗,則把拋LoginException異常
    21                 loginSuccess = true;
    22                                 //登錄成功后,可以返回Subject對象 1.(保存一組(Set)Principal對象),一般保存人員信息
    23                                 //2.(保存一組(Set) Credential Object getPublicCredentials(Class<T> c) 一般保存密碼
    24                 subject = lc.getSubject();
    25 
    26                 Iterator it = subject.getPrincipals().iterator();
    27                 while (it.hasNext()) 
    28                     System.out.println("Authenticated: " + it.next().toString());
    29                             
    30                 it = subject.getPublicCredentials(Properties.class).iterator();
    31                 while (it.hasNext()) 
    32                     ((Properties)it.next()).list(System.out);
    33 
    34                 lc.logout(); //注銷
    35             } catch (LoginException lex) {
    36                 System.out.println(lex.getClass().getName() + "" + lex.getMessage());
    37             }
    38         } catch (Exception ex) {
    39             System.out.println(ex.getClass().getName() + "" + ex.getMessage());
    40         }
    41 
    42         System.exit(0);
    43     }
    44 }


    實現步驟如下:
    A:
    //創建LoginContext實例,把login module 名稱和CallbackHandler接口實現
    LoginContext lc = new LoginContext("Example", cbh);

    B:
    lc.login //進行登錄操作,此時,會根據通過java -Djava.security.auth.login.config=jaas.config指定
    //的配置, 加jaas.config文件 jaas.config寫法如下:
    Example {
       RdbmsLoginModule required debug="true" url="jdbc:mysql://localhost/jaasdb?user=root&password=pass" driver="org.gjt.mm.mysql.Driver";
    };

    //login module name
    Example1 {
         //RdbmsLoginModule: module class name
         //required 固定
         //debug url driver都為參數,可以在LoginModule實現類的 initialize(Subject subject, CallbackHandler callbackHandler,
       //         Map sharedState, Map options)方法中取得
       RdbmsLoginModule required debug="true" url="jdbc:mysql://localhost/jaasdb?user=root&password=pass" driver="org.gjt.mm.mysql.Driver";
    };

    接下來,LoginContext會去 回調 CallbackHandler的handle(Callback[] callbacks)方法
    handle方法把傳入的參數Callback[]中找到NameCallback類型,調用NameCallback.setName把
    用戶名傳進去,找到PasswordCallback類型,調用PasswordCallback.setPassword方法把密碼傳進去
    下面來看一下ConsoleCallbackHandler 實現代碼:

     1 public class ConsoleCallbackHandler implements CallbackHandler {
     2 
     3     /**
     4      * <p>Creates a callback handler that prompts and reads from the
     5      * command line for answers to authentication questions.
     6      * This can be used by JAAS applications to instantiate a
     7      * CallbackHandler.
     8      */
     9     public ConsoleCallbackHandler() {
    10     }
    11 
    12     /**
    13      * Handles the specified set of callbacks.
    14      * This class supports NameCallback and PasswordCallback.
    15      *
    16      * @param   callbacks the callbacks to handle
    17      * @throws  IOException if an input or output error occurs.
    18      * @throws  UnsupportedCallbackException if the callback is not an
    19      * instance of NameCallback or PasswordCallback
    20      */
    21     public void handle(Callback[] callbacks) 
    22         throws java.io.IOException, UnsupportedCallbackException {
    23 
    24         for (int i = 0; i < callbacks.length; i++) {
    25                         System.out.println(callbacks[i]);
    26             if (callbacks[i] instanceof NameCallback) {
    27                 System.out.print(((NameCallback)callbacks[i]).getPrompt());
    28                 String user=(new BufferedReader(new InputStreamReader(System.in))).readLine();
    29                 //設置用戶名
    30                 ((NameCallback)callbacks[i]).setName(user);
    31             } else if (callbacks[i] instanceof PasswordCallback) {
    32                 System.out.print(((PasswordCallback)callbacks[i]).getPrompt());
    33                 String pass=(new BufferedReader(new InputStreamReader(System.in))).readLine();
    34                 //設置密碼
    35                 ((PasswordCallback)callbacks[i]).setPassword(pass.toCharArray());
    36             } else {
    37                 throw(new UnsupportedCallbackException(
    38                             callbacks[i], "Callback class not supported"));
    39             }
    40         }
    41     }
    42 }
    43 

    C:
    接下來,loginContext會 回調依次調用 LoginModule的 方法, 次序如下:
    LoginModule.login
    LoginModule.commit

    如果commit返回 false,則會調用 LoginModule.abort方法
    看一下RdbmsLoginModule類的實現:
      1 public class RdbmsLoginModule implements LoginModule {
      2 
      3     // initial state
      4     CallbackHandler callbackHandler;
      5     Subject  subject;
      6     Map      sharedState;
      7     Map      options;
      8 
      9     // temporary state
     10     Vector   tempCredentials;
     11     Vector   tempPrincipals;
     12 
     13     // the authentication status
     14     boolean  success;
     15 
     16     // configurable options
     17     boolean  debug;
     18     String   url;
     19     String   driverClass;
     20 
     21     /**
     22      * <p>Creates a login module that can authenticate against
     23      * a JDBC datasource.
     24      */
     25     public RdbmsLoginModule() {
     26         tempCredentials = new Vector();
     27         tempPrincipals  = new Vector();
     28         success = false;
     29         debug   = false;
     30     }
     31 
     32     /**
     33      * Initialize this <code>LoginModule</code>.
     34      *
     35      * <p>
     36      *
     37      * @param subject the <code>Subject</code> to be authenticated. <p>
     38      *
     39      * @param callbackHandler a <code>CallbackHandler</code> for communicating
     40      *            with the end user (prompting for usernames and
     41      *            passwords, for example). <p>
     42      *
     43      * @param sharedState shared <code>LoginModule</code> state. <p>
     44      *
     45      * @param options options specified in the login
     46      *            <code>Configuration</code> for this particular
     47      *            <code>LoginModule</code>.
     48      */
     49     public void initialize(Subject subject, CallbackHandler callbackHandler,
     50             Map sharedState, Map options) {
     51 
     52         // save the initial state
     53         this.callbackHandler = callbackHandler;
     54         this.subject     = subject;
     55         this.sharedState = sharedState;
     56         this.options     = options;
     57 
     58         // initialize any configured options
     59         if (options.containsKey("debug"))
     60             debug = "true".equalsIgnoreCase((String)options.get("debug"));
     61 
     62         url          = (String)options.get("url");
     63         driverClass  = (String)options.get("driver");
     64 
     65         if (debug) {
     66             System.out.println("\t\t[RdbmsLoginModule] initialize");
     67             System.out.println("\t\t[RdbmsLoginModule] url: " + url);
     68             System.out.println("\t\t[RdbmsLoginModule] driver: " + driverClass);
     69         }
     70     }
     71 
     72     /**
     73      * <p> Verify the password against the relevant JDBC datasource.
     74      *
     75      * @return true always, since this <code>LoginModule</code>
     76      *      should not be ignored.
     77      *
     78      * @exception FailedLoginException if the authentication fails. <p>
     79      *
     80      * @exception LoginException if this <code>LoginModule</code>
     81      *      is unable to perform the authentication.
     82      */
     83     public boolean login() throws LoginException {
     84 
     85         if (debug)
     86             System.out.println("\t\t[RdbmsLoginModule] login");
     87 
     88         if (callbackHandler == null)
     89             throw new LoginException("Error: no CallbackHandler available " +
     90                     "to garner authentication information from the user");
     91 
     92         try {
     93             // Setup default callback handlers.
     94             Callback[] callbacks = new Callback[] {
     95                 new NameCallback("Username: "),
     96                 new PasswordCallback("Password: "false)
     97             };
     98 
     99             callbackHandler.handle(callbacks);
    100 
    101             String username = ((NameCallback)callbacks[0]).getName();
    102             String password = new String(((PasswordCallback)callbacks[1]).getPassword());
    103 
    104             ((PasswordCallback)callbacks[1]).clearPassword();
    105 
    106             success = rdbmsValidate(username, password);
    107 
    108             callbacks[0= null;
    109             callbacks[1= null;
    110 
    111             if (!success)
    112                 throw new LoginException("Authentication failed: Password does not match");
    113 
    114             return(true);
    115         } catch (LoginException ex) {
    116             throw ex;
    117         } catch (Exception ex) {
    118             success = false;
    119             throw new LoginException(ex.getMessage());
    120         }
    121     }
    122 
    123     /**
    124      * Abstract method to commit the authentication process (phase 2).
    125      *
    126      * <p> This method is called if the LoginContext's
    127      * overall authentication succeeded
    128      * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
    129      * succeeded).
    130      *
    131      * <p> If this LoginModule's own authentication attempt
    132      * succeeded (checked by retrieving the private state saved by the
    133      * <code>login</code> method), then this method associates a
    134      * <code>RdbmsPrincipal</code>
    135      * with the <code>Subject</code> located in the
    136      * <code>LoginModule</code>.  If this LoginModule's own
    137      * authentication attempted failed, then this method removes
    138      * any state that was originally saved.
    139      *
    140      * <p>
    141      *
    142      * @exception LoginException if the commit fails
    143      *
    144      * @return true if this LoginModule's own login and commit
    145      *      attempts succeeded, or false otherwise.
    146      */
    147     public boolean commit() throws LoginException {
    148 
    149         if (debug)
    150             System.out.println("\t\t[RdbmsLoginModule] commit");
    151 
    152         if (success) {
    153 
    154             if (subject.isReadOnly()) {
    155                 throw new LoginException ("Subject is Readonly");
    156             }
    157 
    158             try {
    159                 Iterator it = tempPrincipals.iterator();
    160                 
    161                 if (debug) {
    162                     while (it.hasNext())
    163                         System.out.println("\t\t[RdbmsLoginModule] Principal: " + it.next().toString());
    164                 }
    165 
    166                 subject.getPrincipals().addAll(tempPrincipals);
    167                 subject.getPublicCredentials().addAll(tempCredentials);
    168 
    169                 tempPrincipals.clear();
    170                 tempCredentials.clear();
    171 
    172                 if(callbackHandler instanceof PassiveCallbackHandler)
    173                     ((PassiveCallbackHandler)callbackHandler).clearPassword();
    174 
    175                 return(true);
    176             } catch (Exception ex) {
    177                 ex.printStackTrace(System.out);
    178                 throw new LoginException(ex.getMessage());
    179             }
    180         } else {
    181             tempPrincipals.clear();
    182             tempCredentials.clear();
    183             return(true);
    184         }
    185     }
    186 
    187     /**
    188      * <p> This method is called if the LoginContext's
    189      * overall authentication failed.
    190      * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
    191      * did not succeed).
    192      *
    193      * <p> If this LoginModule's own authentication attempt
    194      * succeeded (checked by retrieving the private state saved by the
    195      * <code>login</code> and <code>commit</code> methods),
    196      * then this method cleans up any state that was originally saved.
    197      *
    198      * <p>
    199      *
    200      * @exception LoginException if the abort fails.
    201      *
    202      * @return false if this LoginModule's own login and/or commit attempts
    203      *     failed, and true otherwise.
    204      */
    205     public boolean abort() throws javax.security.auth.login.LoginException {
    206 
    207         if (debug)
    208             System.out.println("\t\t[RdbmsLoginModule] abort");
    209 
    210         // Clean out state
    211         success = false;
    212 
    213         tempPrincipals.clear();
    214         tempCredentials.clear();
    215 
    216         if (callbackHandler instanceof PassiveCallbackHandler)
    217             ((PassiveCallbackHandler)callbackHandler).clearPassword();
    218 
    219         logout();
    220 
    221         return(true);
    222     }
    223 
    224     /**
    225      * Logout a user.
    226      *
    227      * <p> This method removes the Principals
    228      * that were added by the <code>commit</code> method.
    229      *
    230      * <p>
    231      *
    232      * @exception LoginException if the logout fails.
    233      *
    234      * @return true in all cases since this <code>LoginModule</code>
    235      *        should not be ignored.
    236      */
    237     public boolean logout() throws javax.security.auth.login.LoginException {
    238 
    239         if (debug)
    240             System.out.println("\t\t[RdbmsLoginModule] logout");
    241 
    242         tempPrincipals.clear();
    243         tempCredentials.clear();
    244 
    245         if (callbackHandler instanceof PassiveCallbackHandler)
    246             ((PassiveCallbackHandler)callbackHandler).clearPassword();
    247 
    248         // remove the principals the login module added
    249         Iterator it = subject.getPrincipals(RdbmsPrincipal.class).iterator();
    250         while (it.hasNext()) {
    251             RdbmsPrincipal p = (RdbmsPrincipal)it.next();
    252             if(debug)
    253                 System.out.println("\t\t[RdbmsLoginModule] removing principal "+p.toString());
    254             subject.getPrincipals().remove(p);
    255         }
    256 
    257         // remove the credentials the login module added
    258         it = subject.getPublicCredentials(RdbmsCredential.class).iterator();
    259         while (it.hasNext()) {
    260             RdbmsCredential c = (RdbmsCredential)it.next();
    261             if(debug)
    262                 System.out.println("\t\t[RdbmsLoginModule] removing credential "+c.toString());
    263             subject.getPrincipals().remove(c);
    264         }
    265 
    266         return(true);
    267     }
    268 
    269     /**
    270      * Validate the given user and password against the JDBC datasource.
    271      * <p>
    272      *
    273      * @param user the username to be authenticated. <p>
    274      * @param pass the password to be authenticated. <p>
    275      * @exception Exception if the validation fails.
    276      */
    277     private boolean rdbmsValidate(String user, String pass) throws Exception {
    278         
    279         Connection con;
    280         String query = "SELECT * FROM USER_AUTH where userid='" + user + "'";
    281         Statement stmt;
    282         RdbmsPrincipal  p = null;
    283         RdbmsCredential c = null;
    284         boolean passwordMatch = false;
    285 
    286         try {
    287             Class.forName(driverClass);
    288         }
    289         catch (java.lang.ClassNotFoundException e) {
    290             System.err.print("ClassNotFoundException: ");
    291             System.err.println(e.getMessage());
    292             throw new LoginException("Database driver class not found: " + driverClass);
    293         }
    294 
    295         try {
    296             if (debug)
    297                 System.out.println("\t\t[RdbmsLoginModule] Trying to connect");
    298 
    299             con = DriverManager.getConnection(url, "Administrator""");
    300 
    301             if (debug)
    302                 System.out.println("\t\t[RdbmsLoginModule] connected!");
    303 
    304             stmt = con.createStatement();
    305 
    306             if (debug)
    307                 System.out.println("\t\t[RdbmsLoginModule] "+query);
    308 
    309             ResultSet result  = stmt.executeQuery(query);
    310             String dbPassword = null, dbFname = null, dbLname = null;
    311             String updatePerm = null, deletePerm = null;
    312             boolean isEqual   = false;
    313 
    314             while (result.next()) {
    315                 if (!result.isFirst()) 
    316                     throw new LoginException("Ambiguous user (located more than once): "+user);
    317                 dbPassword = result.getString(result.findColumn("password"));
    318                 dbFname    = result.getString(result.findColumn("first_name"));
    319                 dbLname    = result.getString(result.findColumn("last_name"));
    320                 deletePerm = result.getString(result.findColumn("delete_perm"));
    321                 updatePerm = result.getString(result.findColumn("update_perm"));
    322             }
    323 
    324             if (dbPassword == null)
    325                 throw new LoginException("User " + user + " not found");
    326 
    327             if (debug)
    328                 System.out.println("\t\t[RdbmsLoginModule] '"+pass + "' equals '" + dbPassword + "'?");
    329 
    330             passwordMatch = pass.equals(dbPassword);
    331             if (passwordMatch) {
    332                 if (debug) 
    333                     System.out.println("\t\t[RdbmsLoginModule] passwords match!");
    334 
    335                 c = new RdbmsCredential();
    336                 c.setProperty("delete_perm", deletePerm);
    337                 c.setProperty("update_perm", updatePerm);
    338                 this.tempCredentials.add(c);
    339                 this.tempPrincipals.add(new RdbmsPrincipal(dbFname + " " + dbLname));
    340             } else {
    341                 if (debug)
    342                     System.out.println("\t\t[RdbmsLoginModule] passwords do NOT match!");
    343             }
    344             stmt.close();
    345             con.close();
    346         }
    347         catch (SQLException ex) {
    348             System.err.print("SQLException: ");
    349             System.err.println(ex.getMessage());
    350             throw new LoginException("SQLException: "+ex.getMessage());
    351         }
    352         return(passwordMatch);
    353     }
    354 }
    355 

    Good Luck!
    Yours Matthew!
    posted on 2008-05-28 09:27 x.matthew 閱讀(2685) 評論(2)  編輯  收藏 所屬分類: Spring|Hibernate|Other framework
    主站蜘蛛池模板: 在线免费不卡视频| 在线观看亚洲专区| 国产精品亚洲mnbav网站 | 最近中文字幕电影大全免费版| 粉色视频在线观看www免费| 亚洲日本视频在线观看| 亚洲欧洲国产精品香蕉网| 又粗又大又猛又爽免费视频| 免费精品国偷自产在线在线 | 亚洲欧洲日本在线| 国产大片91精品免费观看男同| 又黄又爽又成人免费视频| 久久狠狠躁免费观看| a色毛片免费视频| 国产人成网在线播放VA免费| 欧洲乱码伦视频免费国产| 爱情岛论坛亚洲品质自拍视频网站 | 亚洲成AV人片在线观看| 亚洲女同成av人片在线观看| 亚洲精品一级无码鲁丝片| 免费h成人黄漫画嘿咻破解版| 久久久www成人免费毛片| 成人免费大片免费观看网站| 99视频在线精品免费| 日韩免费无码一区二区三区| 精品视频在线免费观看| a级毛片免费全部播放| 国产精品免费一区二区三区| 51午夜精品免费视频| GOGOGO高清免费看韩国| 国产精品无码免费专区午夜| 国产精品午夜免费观看网站| 一个人免费观看视频在线中文 | 大陆一级毛片免费视频观看| 最近中文字幕无免费视频| 曰批全过程免费视频在线观看| 一个人在线观看视频免费| 成年人网站在线免费观看| 日韩高清在线高清免费| 亚洲AV无码乱码在线观看性色扶| 亚洲一区二区三区在线视频|