1. 程式人生 > >shiro中的reaml理解及實現機制

shiro中的reaml理解及實現機制

rmi 我們 身份認證 理解 例子 generated std dbutil sets

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;
10 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 }
View Code

其中:

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理解及實現機制