shiro中的reaml理解及實現機制
shiro中的reaml非常重要,所有的身份數據驗證都在reaml中實現。可以把Realm看成DataSource,即安全數據源。
Shiro從Realm獲取安全數據(如用戶、角色、權限),就是說SecurityManager要驗證用戶身份,那麽它需要從Realm獲取相應的用戶進行比較以確定用戶身份是否合法;
也需要從Realm得到用戶相應的角色/權限進行驗證用戶是否能進行操作。
下面以例子講解其實現機制:
最開始用戶、角色、權限都配置在shiro.ini配置文件中。
但實際項目中更多的是保存數據庫中,因此reaml就應運而生,很好的幫我們做到了這一點。所有的身份認證都需經過它。
shiro配置文件中只需配置Reaml,用戶和角色就不需配置了
我們需要給Shiro的SecurityManager註入自定義Realm
自定義Realm中只需繼承抽象類AuthorizingRealm即可,重寫身份認證和權限認證方法。
1 /** 2 * 3 */ 4 package com.hik.realm; 5 6 import java.sql.Connection; 7 import java.sql.SQLException; 8 9 import org.apache.shiro.authc.AuthenticationException;View Code10 import org.apache.shiro.authc.AuthenticationInfo; 11 import org.apache.shiro.authc.AuthenticationToken; 12 import org.apache.shiro.authc.SimpleAuthenticationInfo; 13 import org.apache.shiro.authz.AuthorizationInfo; 14 import org.apache.shiro.authz.SimpleAuthorizationInfo; 15 import org.apache.shiro.realm.AuthorizingRealm;16 import org.apache.shiro.subject.PrincipalCollection; 17 18 import com.hik.dao.UserDao; 19 import com.hik.entity.User; 20 import com.hik.util.Dbutil; 21 22 /** 23 * @ClassName: MyRealm 24 * @Description: TODO 25 * @author jed 26 * @date 2017年7月22日下午4:33:44 27 * 28 */ 29 public class MyRealm extends AuthorizingRealm{ 30 31 private Dbutil dbutil=new Dbutil(); 32 private UserDao userDao = new UserDao(); 33 34 /** 35 *為當前登錄的用戶授予角色和權限 36 */ 37 @Override 38 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { 39 String userName = (String) principals.getPrimaryPrincipal(); 40 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); 41 Connection con = null; 42 try { 43 con = dbutil.getConnection(); 44 authorizationInfo.setRoles(userDao.getRoles(con, userName)); 45 authorizationInfo.setStringPermissions(userDao.getPermissions(con, userName)); 46 } catch (Exception e) { 47 // TODO Auto-generated catch block 48 e.printStackTrace(); 49 }finally { 50 try { 51 con.close(); 52 } catch (SQLException e) { 53 // TODO Auto-generated catch block 54 e.printStackTrace(); 55 } 56 } 57 return authorizationInfo; 58 } 59 60 /** 61 * 驗證當前登錄的用戶 62 */ 63 @Override 64 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 65 String userName = (String)token.getPrincipal(); 66 Connection con = null; 67 try { 68 con =dbutil.getConnection(); 69 User currentUser = userDao.getUserByUserName(con, userName); 70 if(currentUser!=null){ 71 AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(currentUser.getUserName(),currentUser.getPassword(),"myRealm"); 72 return authcInfo; 73 }else{ 74 return null; 75 } 76 } catch (Exception e) { 77 // TODO Auto-generated catch block 78 e.printStackTrace(); 79 }finally { 80 try { 81 con.close(); 82 } catch (SQLException e) { 83 // TODO Auto-generated catch block 84 e.printStackTrace(); 85 } 86 } 87 return null; 88 } 89 90 }
其中:
doGetAuthenticationInfo :身份認證(驗證當前登錄的用戶)
doGetAuthorizationInfo :身份認證通過,該身份擁有的角色和權限。為當前登錄的用戶授予角色和權限。
當用戶在拿到token(前臺傳過來用戶名和密碼生成)進行登錄時,
登入代碼
1 @Override 2 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 3 System.out.println("login dopost"); 4 log.info("login dopost"); 5 String userName = req.getParameter("userName"); 6 String password = req.getParameter("password"); 7 UsernamePasswordToken token = new UsernamePasswordToken(userName,password); 8 Subject subject = SecurityUtils.getSubject(); 9 Session session = subject.getSession(); 10 System.out.println("sessionId: "+session.getId()); 11 System.out.println("sessionHost: "+session.getHost()); 12 System.out.println("sessionTimeout: "+session.getTimeout()); 13 session.setAttribute("info", "session的數據"); 14 try{ 15 subject.login(token); 16 resp.sendRedirect("success.jsp"); //重定向 17 }catch(Exception e){ 18 log.error("登錄失敗", e); 19 req.setAttribute("errorInfo", "用戶名或者密碼錯誤"); 20 req.getRequestDispatcher("login.jsp").forward(req, resp);//請求轉發 21 } 22 }View Code
subject.login(token);
進入自定義realm(繼承AuthorizingRealm)的doGetAuthenticationInfo方法和doGetAuthorizationInfo方法
doGetAuthenticationInfo :進行身份認證(驗證當前登錄的用戶,token中獲取的用戶與後臺數據庫用戶進行比對,存在則身份認證通過)。
一旦身份認證通過後,進入doGetAuthorizationInfo方法 則查詢該身份擁有的角色及賦予的權限,並為當前登錄的用戶授予角色和權限。
整個過程完成,則實現了用戶的身份認證,及角色和權限授予。
其實 Realm看成DataSource,即安全數據源。
shiro中的reaml理解及實現機制