package com.shiro.bean; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.realm.AuthenticatingRealm; import org.apache.shiro.util.ByteSource; /** * @author layne * Action方法中執行subject.login(token)時會通過IOC容器調取Realm域進行數據和前端數據比對 */ public class ShiroRealm extends AuthenticatingRealm { /** * Returns all principals associated with the corresponding Subject. Each principal is an identifying piece of * information useful to the application such as a username, or user id, a given name, etc - anything useful * to the application to identify the current <code>Subject</code>. * The returned PrincipalCollection should <em>not</em> contain any credentials used to verify principals, such * as passwords, private keys, etc. Those should be instead returned by {@link #getCredentials() getCredentials()}. * @return all principals associated with the corresponding Subject. * * doGetAuthenticationInfo,獲取認證消息,如果數據庫沒有數據,返回null. * AuthenticationInfo可以使用 SimpleAuthenticationInfo實現類,封裝給正確用戶名和密碼 * token參數:需要驗證的token */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { /** * 1.將token轉換為UsernamePasswordToken * 2.獲取用戶名 * 3.查詢數據庫,進行驗證 * 4.結果返回 * 5.驗證不通過,拋出異常 */ //1.將token轉換為UsernamePasswordToken UsernamePasswordToken upToken = (UsernamePasswordToken)token; //2.獲取用戶名 String userName = upToken.getUsername(); //獲取用戶名后。通過查詢用戶名查詢數據庫是否有值,有值則進行密碼驗證。 SimpleAuthenticationInfo info=null; //3。查詢數據庫 //使用JDBC鏈接數據庫進行查詢 try { Class.forName("com.mysql.jdbc.Driver"); String url="jdbc:mysql://localhost:3306/test"; Connection conn=DriverManager.getConnection(url,"root",""); PreparedStatement ps = conn.prepareStatement("select * from account where name=?"); ps.setString(1, userName); ResultSet rs = ps.executeQuery(); if(rs.next()){ Object principal=userName; Object credentials=rs.getString(3); String realmName=this.getName(); //設置鹽值 ByteSource salt=ByteSource.Util.bytes(userName); //SimpleHash sh=new SimpleHash(algorithmName, source, salt, iterations); // 加密類型 加密資源 鹽值加密 加密次數 //給從數據庫中拿到的密碼做MD5的加密 SimpleHash sh=new SimpleHash("MD5", credentials, salt, 1024); //info = new SimpleAuthenticationInfo(principal, credentials, realmName); //info = new SimpleAuthenticationInfo(principal, sh, realmName); //通過關於鹽值的構造器,將前端傳入的密碼在加密時再加入鹽值 info = new SimpleAuthenticationInfo(principal, sh, salt, realmName); }else{ throw new AuthenticationException(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return info; } }