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;
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,即安全数据源。

    

posted @ 2017-07-22 18:34  心和梦的方向  阅读(923)  评论(0编辑  收藏  举报