zoukankan      html  css  js  c++  java
  • Shrio授权验证详解

    所谓授权,就是控制你是否能访问某个资源,比如说,你可以方位page文件夹下的jsp页面,但是不可以访问page文件夹下的admin文件夹下的jsp页面。

    在授权中,有三个核心元素:权限,角色,用户。

    每个用户可以有多个角色,每个角色也可以有多个权限。

    权限:代表了可以执行的行为,例如对表的读写之类的。

    角色:代表了一组权限

    用户:代表了一个subject,可以为用户赋予角色,或者直接赋予权限。


     授权验证详解

    在Shiro中共有三种授权的验证方式:编程式、注解式、JSP/GSP标签。

    编程授权验证

    最早的方式就是通过编程的方式,直接通过Subject来判断权限,角色等。

    如果要判断当前用户是否有某个权限,可以通过hasRole方法来判断,如果有某权限的话,则干嘛,没有的话则干嘛。

    Subject currentUser = SecurityUtils.getSubject();
    
    if (currentUser.hasRole("administrator")) {
        //show the admin button 
    } else {
        //don't show the button?  Grey it out? 
    }

    在Shrio中,提供了下面几个检测权限的方式:

    hasRole(String roleName) 如果当前用户有这个角色,则返回true
    hasRoles(List<String> roleNames) 返回一个是否有当前每个角色的结果集
    hasAllRoles(Collection<String> roleNames) 如果有所有的权限的话,则返回true

    另外还有一种方式,就是调用checkRole方法来检测是否有特定的权限,如果有的话,则不会报错,没有的话则会抛出AuthorizationException异常。

    Subject currentUser = SecurityUtils.getSubject();
    
    //guarantee that the current user is a bank teller and 
    //therefore allowed to open the account: 
    currentUser.checkRole("bankTeller");
    openBankAccount();

    在Shrio中,也提供了下面的几个方法来检测权限:

    checkRole(String roleName) 如果没有这个权限则报错
    checkRoles(Collection<String> roleNames) 如果没有这其中的某个权限都会报错
    checkRole(String... roleNames) 如果没有这其中的某个权限都会报错

     

     

    如果要检测是否有某个权限的话,则可以通过isPermitted方法来检测。

     这个方法可以接收Permission对象也可以接收字符串的权限信息。

    Permission printPermission = new PrinterPermission("laserjet4400n", "print");
    
    Subject currentUser = SecurityUtils.getSubject();
    
    if (currentUser.isPermitted(printPermission)) {
        //show the Print button 
    } else {
        //don't show the button?  Grey it out?
    }

    或者

    Subject currentUser = SecurityUtils.getSubject();
    
    if (currentUser.isPermitted("printer:print:laserjet4400n")) {
        //show the Print button
    } else {
        //don't show the button?  Grey it out? 
    }

    在Shrio里面提供了下面的几个方法来检测权限。

    isPermitted(Permission p) 如果有这个权限的话就返回true
    isPermitted(String perm) 如果有这个权限的话就返回true
    isPermitted(List<Persisson> perms) 返回每个权限是否有的true或false的结果集
    isPermitted(String ... perms) 返回每个权限是否有的true或false的结果集
    isPermittedAll(Collection<Permission> perms) 如果拥有所有的权限则返回true
    isPermittedALL(String ...Perms) 如果拥有所有的权限则返回true

    跟角色一样,也同样有下面的替换方式:

    Subject currentUser = SecurityUtils.getSubject();
    
    //guarantee that the current user is permitted 
    //to open a bank account: 
    Permission p = new AccountPermission("open");
    currentUser.checkPermission(p);
    openBankAccount();

    或者

    Subject currentUser = SecurityUtils.getSubject();
    
    //guarantee that the current user is permitted 
    //to open a bank account: 
    currentUser.checkPermission("account:open");
    openBankAccount();

    也有下面几种方法:

    checkPermission(Permission p) 如果没有这个权限就会抛出异常
    checkPermission(String perm) 如果没有这个权限就会抛出异常
    checkPermissions(Collection<permission> perms) 如果没有这些权限中的某一个就会抛出异常
    checkPermissions(String ... perms) 如果没有这些权限中的某一个就会抛出异常

     


    注解授权验证

    Shiro的注解授权需要Java5以上的支持。

    如果要想使用的话,还需要使用AOP的支持。在市面上也有很多中AOP支持,比如apache的Aspectj、Spring之类的。

    RequiresAuthentication

    这个注解表示要求当前用户对这个类,接口或者方法访问的时候,需要是已经被认证的。

    @RequiresAuthentication
    public void updateAccount(Account userAccount) {
        //this method will only be invoked by a
        //Subject that is guaranteed authenticated
        ...
    }

    RequireGuest

    RequireGuest注解要求当前用户在访问这个类、接口或方法的时候是一个游客,也就是说没有登陆或者通过上演一次登陆的时候记住密码了。

    @RequiresGuest
    public void signUp(User newUser) {
        //this method will only be invoked by a
        //Subject that is unknown/anonymous
        ...
    }

    RequiresPermissions

    RequiresPermission注解要求当前用户用户有着权限。

    @RequiresPermissions("account:create")
    public void createAccount(Account account) {
        //this method will only be invoked by a Subject
        //that is permitted to create an account
        ...
    }

    RequiresRoles

    RequiresRoles注解要求当前用户拥有这个角色才可以访问,否则抛出异常。

    @RequiresRoles("administrator")
    public void deleteUser(User user) {
        //this method will only be invoked by an administrator
        ...
    }

    RequiresUser

    RequiresUser要求当前用户必须是指定的用户才能够访问这个类、接口或者方法。

    @RequiresUser
    public void updateAccount(Account account) {
        //this method will only be invoked by a 'user'
        //i.e. a Subject with a known identity
        ...
    }

    JSP/GSP标签授权验证

     标签的授权验证用来支持在web开发中的权限控制。


    授权顺序 

     前面我们讲了三种权限的控制方式,接下来我们看看权限控制的流程是什么样的。

    下面是一张权限控制的结构图。

    Step1:当前用户调用检测角色,权限的方法

    step2:当前用户实例(通常是一个DelegatingSubject)通过调用SecurityManager的检测角色权限的方法,把任务转发给SecurityManager。

    Step3:SecurityManager作为一个容器,把检测权限的任务转发给内部的验证器,验证器通常默认是一个ModularRealmAuthorizer实例,会通过Realm来检测用户的权限。

    Step4:每一个Realm都会被用来检测是否支持当前的认证,支持的话则会调用Realm的方法来检测是否有当前权限。


    角色与权限配置

    角色域与权限的配置可以在INI文件或者数据库中配置,具体在那取决于我们具体采用哪种Realm的认证方式。

    shiro.ini文件中配置

    在shiro.ini配置文件中我们可以配置[main],[users],[roles],[urls]四个节,其中[roles]就是用来配置角色与权限的。

    例如:

    [roles]
    # 'admin' role has all permissions, indicated by the wildcard '*'
    admin = *
    # The 'schwartz' role can do anything (*) with any lightsaber:
    schwartz = lightsaber:*
    # The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
    # license plate 'eagle5' (instance specific id)
    goodguy = winnebago:drive:eagle5

    如果要让某个角色拥有多个权限,则可以用都厚隔开,指定多个权限即可。

    实例(通过ini文件)

    首先在配置文件中配置权限信息,“*”是通配符。

    [users]
    fuwh=123456,admin
    zhangsan=123,buzhang,yuangong
    lisi=12,yuangong
    
    [roles]
    admin=*
    buzhang=bumen:*
    yuangong=bumen:diwubu:query

    编写登陆权限认证程序:

    package com.fuwh.demo;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.Permission;
    import org.apache.shiro.authz.permission.WildcardPermission;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class ShiroDemo03 {
        
        private static Logger log=LoggerFactory.getLogger(ShiroDemo03.class);
        public static void main(String[] args) {
            //取得SecurityManager工厂
            Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro.ini");
            //取得SecurityManager实例
            SecurityManager securityManager=factory.getInstance();
            //将securityManager绑定到SecurityUtil
            SecurityUtils.setSecurityManager(securityManager);
    
            //取得当前用户
            Subject subject=SecurityUtils.getSubject();
            
            //使用fuwh来进行登陆验证
            if(!subject.isAuthenticated()) {
                UsernamePasswordToken token=new UsernamePasswordToken("fuwh","123456");
                try {
                    subject.login(token);
                    log.info(token.getPrincipal()+"登陆成功!!!");
                    if(subject.hasRole("admin")) {
                        log.info(token.getPrincipal()+"有admin的角色");
                        Permission p1=new WildcardPermission("bumen:*:query");
                        if(subject.isPermitted(p1)) {
                            log.info(token.getPrincipal()+"有bumen:*:query的权限");
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("认证失败...");
                }
            }
            subject.logout();
            
            log.debug("*****************************************************************");
            
            if(!subject.isAuthenticated()) {
                UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","123");
                try {
                    subject.login(token);
                    log.info(token.getPrincipal()+"登陆成功!!!");
                    if(subject.hasRole("yuangong")) {
                        log.info(token.getPrincipal()+"有yuangong的角色");
                        Permission p1=new WildcardPermission("bumen:diwubu:query");
                        if(subject.isPermitted(p1)) {
                            log.info(token.getPrincipal()+"有bumen:diwubu:query的权限");
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("认证失败...");
                }
            }
            subject.logout();
            
            log.debug("*****************************************************************");
            
            if(!subject.isAuthenticated()) {
                UsernamePasswordToken token=new UsernamePasswordToken("lisi","12");
                try {
                    subject.login(token);
                    log.info(token.getPrincipal()+"登陆成功!!!");
                    if(subject.hasRole("yuangong")) {
                        log.info(token.getPrincipal()+"有yuangong的角色");
                        Permission p1=new WildcardPermission("bumen:diwubu:update");
                        if(subject.isPermitted(p1)) {
                            log.info(token.getPrincipal()+"有bumen:diwubu:update的权限");
                        }else {
                            log.info(token.getPrincipal()+"没有bumen:diwubu:update的权限");
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("认证失败...");
                }
            }
            subject.logout();
        }
    }

    执行后,输出结果:

    2017-08-27 14:08:36,089 [main] INFO  [org.apache.shiro.session.mgt.AbstractValidatingSessionManager] - Enabling session validation scheduler...
    2017-08-27 14:08:36,640 [main] INFO  [com.fuwh.demo.ShiroDemo03] - fuwh登陆成功!!!
    2017-08-27 14:08:36,640 [main] INFO  [com.fuwh.demo.ShiroDemo03] - fuwh有admin的角色
    2017-08-27 14:08:36,641 [main] INFO  [com.fuwh.demo.ShiroDemo03] - fuwh有bumen:*:query的权限
    2017-08-27 14:08:36,643 [main] INFO  [com.fuwh.demo.ShiroDemo03] - zhangsan登陆成功!!!
    2017-08-27 14:08:36,643 [main] INFO  [com.fuwh.demo.ShiroDemo03] - zhangsan有yuangong的角色
    2017-08-27 14:08:36,643 [main] INFO  [com.fuwh.demo.ShiroDemo03] - zhangsan有bumen:diwubu:query的权限
    2017-08-27 14:08:36,644 [main] INFO  [com.fuwh.demo.ShiroDemo03] - lisi登陆成功!!!
    2017-08-27 14:08:36,644 [main] INFO  [com.fuwh.demo.ShiroDemo03] - lisi有yuangong的角色
    2017-08-27 14:08:36,644 [main] INFO  [com.fuwh.demo.ShiroDemo03] - lisi没有bumen:diwubu:update的权限

    需要解释一下的是,如果某个角色的权限是"*",则代表拥有所有的权限。而如果只想让用户拥有某个部门的员工的所有权限的话怎么办呢?

    在Shrio中支持分层的权限写法,例如:emp=bumen:yuangong:*,这样的分层则更容易的对权限来进行控制,

    如果角色的权限为emp=bumen:update,则等价于emp=bumen:*:updae。

    同时,emp=bumen:yuangong也等价于emp=bumen:yuangong:*。

    通过Shiro自带的JdbcRealm

    在JdbcReal中,默认的角色与权限的查询是通过静态变量DEFAULT_USER_ROLES_QUERY和DEFAULT_PERMISSIONS_QUERY中定义的sql语句来查询的。

    DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";

    DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";

    并分别把他们的值赋给userRolesQuery和permissionsQuery。

    所以默认情况下是从user_roles表中去查询角色信息,从roles_permissions表中去查询权限信息。

    如果需要自定义表名,列名的话,可以通过在配置文件中覆写这两个sql语句。

    实例

    首先建立数据库如下:

    USE `db_shiro`;
    
    DROP TABLE IF EXISTS `users`;
    
    CREATE TABLE `users` (
      `id` int(4) NOT NULL AUTO_INCREMENT,
      `username` varchar(20) DEFAULT NULL,
      `password` varchar(100) DEFAULT NULL,
      UNIQUE KEY `id` (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    insert  into `users`(`id`,`username`,`password`) values (1,'fuwh','123456'),(2,'zhangsan','123'),(3,'lisi','12');
    
    DROP TABLE IF EXISTS `user_roles`;
    
    CREATE TABLE `user_roles` (
      `username` varchar(20) NOT NULL,
      `role_name` varchar(20) NOT NULL,
      `role_desc` varchar(100) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    insert  into `user_roles`(`username`,`role_name`,`role_desc`) values ('fuwh','admin','管理员'),('zhangsan','buzhang','部长'),('lisi','yuangong','员工'),('zhangsan','yuangong','员工');
    
    DROP TABLE IF EXISTS `roles_permissions`;
    
    CREATE TABLE `roles_permissions` (
      `role_name` varchar(20) NOT NULL,
      `permission` varchar(20) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    insert  into `roles_permissions`(`role_name`,`permission`) values ('admin','*'),('buzhang','bumen:*'),('yuangong','bumen:diwubu:query');

    编写配置文件:

    [main]
    dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
    dataSource.driverClass=com.mysql.jdbc.Driver
    dataSource.jdbcUrl=jdbc:mysql://localhost:3306/db_shiro
    dataSource.user=root
    dataSource.password=rootadmin
    
    jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
    jdbcRealm.dataSource=$dataSource
    securityManager.realms=$jdbcRealm

    编写授权代码:

    package com.fuwh.demo;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.Permission;
    import org.apache.shiro.authz.permission.WildcardPermission;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class ShiroDemoJdbc03 {
        
        private static Logger log=LoggerFactory.getLogger(ShiroDemoJdbc03.class);
        public static void main(String[] args) {
            //取得SecurityManager工厂
            Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro_jdbc.ini");
            //取得SecurityManager实例
            SecurityManager securityManager=factory.getInstance();
            //将securityManager绑定到SecurityUtil
            SecurityUtils.setSecurityManager(securityManager);
    
            /*    至此为止,简单的从mysql数据库读取realm信息的shiro环境就配置好了    */
            
            //取得当前用户
            Subject subject=SecurityUtils.getSubject();
            
            //使用fuwh来进行登陆验证
                    if(!subject.isAuthenticated()) {
                        UsernamePasswordToken token=new UsernamePasswordToken("fuwh","123456");
                        try {
                            subject.login(token);
                            log.info(token.getPrincipal()+"登陆成功!!!");
                            if(subject.hasRole("admin")) {
                                log.info(token.getPrincipal()+"有admin的角色");
                                Permission p1=new WildcardPermission("bumen:*:query");
                                if(subject.isPermitted(p1)) {
                                    log.info(token.getPrincipal()+"有bumen:*:query的权限");
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error("认证失败...");
                        }
                    }
                    subject.logout();
                    
                    log.debug("*****************************************************************");
                    
                    if(!subject.isAuthenticated()) {
                        UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","123");
                        try {
                            subject.login(token);
                            log.info(token.getPrincipal()+"登陆成功!!!");
                            if(subject.hasRole("yuangong")) {
                                log.info(token.getPrincipal()+"有yuangong的角色");
                                Permission p1=new WildcardPermission("bumen:diwubu:query");
                                if(subject.isPermitted(p1)) {
                                    log.info(token.getPrincipal()+"有bumen:diwubu:query的权限");
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error("认证失败...");
                        }
                    }
                    subject.logout();
                    
                    log.debug("*****************************************************************");
                    
                    if(!subject.isAuthenticated()) {
                        UsernamePasswordToken token=new UsernamePasswordToken("lisi","12");
                        try {
                            subject.login(token);
                            log.info(token.getPrincipal()+"登陆成功!!!");
                            if(subject.hasRole("yuangong")) {
                                log.info(token.getPrincipal()+"有yuangong的角色");
                                Permission p1=new WildcardPermission("bumen:diwubu:update");
                                if(subject.isPermitted(p1)) {
                                    log.info(token.getPrincipal()+"有bumen:diwubu:update的权限");
                                }else {
                                    log.info(token.getPrincipal()+"没有bumen:diwubu:update的权限");
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error("认证失败...");
                        }
                    }
                    subject.logout();
        }
    }

    执行结果:

    2017-08-27 14:08:36,089 [main] INFO  [org.apache.shiro.session.mgt.AbstractValidatingSessionManager] - Enabling session validation scheduler...
    2017-08-27 14:08:36,640 [main] INFO  [com.fuwh.demo.ShiroDemo03] - fuwh登陆成功!!!
    2017-08-27 14:08:36,640 [main] INFO  [com.fuwh.demo.ShiroDemo03] - fuwh有admin的角色
    2017-08-27 14:08:36,641 [main] INFO  [com.fuwh.demo.ShiroDemo03] - fuwh有bumen:*:query的权限
    2017-08-27 14:08:36,643 [main] INFO  [com.fuwh.demo.ShiroDemo03] - zhangsan登陆成功!!!
    2017-08-27 14:08:36,643 [main] INFO  [com.fuwh.demo.ShiroDemo03] - zhangsan有yuangong的角色
    2017-08-27 14:08:36,643 [main] INFO  [com.fuwh.demo.ShiroDemo03] - zhangsan有bumen:diwubu:query的权限
    2017-08-27 14:08:36,644 [main] INFO  [com.fuwh.demo.ShiroDemo03] - lisi登陆成功!!!
    2017-08-27 14:08:36,644 [main] INFO  [com.fuwh.demo.ShiroDemo03] - lisi有yuangong的角色
    2017-08-27 14:08:36,644 [main] INFO  [com.fuwh.demo.ShiroDemo03] - lisi没有bumen:diwubu:update的权限

    通过自定义的MyJdbcRealm实现

    创建数据库:

    USE `db_shiro`;
    
    
    DROP TABLE IF EXISTS `members`;
    
    CREATE TABLE `members` (
      `id` INT(4) NOT NULL AUTO_INCREMENT,
      `membername` VARCHAR(20) DEFAULT NULL,
      `password` VARCHAR(100) DEFAULT NULL,
      UNIQUE KEY `id` (`id`)
    ) ENGINE=INNODB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
    
    
    INSERT  INTO `members`(`id`,`membername`,`password`) VALUES (1,'fuwh','123456'),(2,'zhangsan','123'),(3,'lisi','12');
    
    
    DROP TABLE IF EXISTS `roles_permissions`;
    
    CREATE TABLE `roles_permissions` (
      `role_name` VARCHAR(20) NOT NULL,
      `permission` VARCHAR(20) NOT NULL
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    
    
    INSERT  INTO `roles_permissions`(`role_name`,`permission`) VALUES ('admin','*'),('buzhang','bumen:*'),('yuangong','bumen:diwubu:query');
    
    DROP TABLE IF EXISTS `member_roles`;
    
    CREATE TABLE `member_roles` (
      `membername` VARCHAR(20) NOT NULL,
      `role_name` VARCHAR(20) NOT NULL,
      `role_desc` VARCHAR(100) DEFAULT NULL
    ) ENGINE=INNODB DEFAULT CHARSET=utf8;
    
    
    INSERT  INTO `member_roles`(`membername`,`role_name`,`role_desc`) VALUES ('fuwh','admin','管理员'),('zhangsan','buzhang','部长'),('lisi','yuangong','员工'),('zhangsan','yuangong','员工');

    编写MyJdbcRealm

    package com.fuwh.realm;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.LinkedHashSet;
    import java.util.Set;
    
    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.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    
    import com.fuwh.util.DbUtil;
    
    public class MyJdbcRealm extends AuthorizingRealm{
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            // TODO Auto-generated method stub
            SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
            Set<String> roleNames=new LinkedHashSet<String>();
            Connection conn=DbUtil.getConnection();
            String sql="select role_name from member_roles where membername=?";
            try {
                PreparedStatement ps=conn.prepareStatement(sql);
                ps.setString(1, principals.toString());
                ResultSet rs=ps.executeQuery();
                while(rs.next()) {
                    roleNames.add(rs.getString(1));
                }
                rs.close();
                info.setRoles(roleNames);
                try {
                    Set<String> permissions=getPermissions(conn,roleNames);
                    info.setStringPermissions(permissions);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                ps.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return info;
        }
    
        
        protected Set<String> getPermissions(Connection conn,Set<String> roleNames) throws Exception{
            Set<String> permissions=new LinkedHashSet<String>();
            String sql="select permission from roles_permissions where role_name=?";
            PreparedStatement ps=conn.prepareStatement(sql);
            for (String roleName : roleNames) {
                ps.setString(1,roleName);
                ResultSet rs=ps.executeQuery();
                while(rs.next()) {
                    permissions.add(rs.getString("permission"));
                }
                rs.close();
            }
            ps.close();
            return permissions;
        }
        
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            // TODO Auto-generated method stub
            Connection conn=DbUtil.getConnection();
            String sql="select * from members where userName=?";
            try {
                PreparedStatement ps=conn.prepareStatement(sql);
                ps.setString(1, token.getPrincipal().toString());
                ResultSet rs=ps.executeQuery();
                while(rs.next()) {
                    AuthenticationInfo info=new SimpleAuthenticationInfo(rs.getString("userName"),rs.getString("pass"),"salt");
                    return info;
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }
        
    }

    编写配置文件:

    [main]myJdbcRealm=com.fuwh.realm.MyJdbcRealmsecurityManager.realms=$myJdbcRealm

     编写权限认证代码:

    package com.fuwh.demo;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.Permission;
    import org.apache.shiro.authz.permission.WildcardPermission;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.Factory;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class ShiroDemoMyJdbc03 {
        
        private static Logger log=LoggerFactory.getLogger(ShiroDemoMyJdbc03.class);
        public static void main(String[] args) {
            //取得SecurityManager工厂
            Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro_my_jdbc.ini");
            //取得SecurityManager实例
            SecurityManager securityManager=factory.getInstance();
            //将securityManager绑定到SecurityUtil
            SecurityUtils.setSecurityManager(securityManager);
    
            /*    至此为止,简单的从mysql数据库读取realm信息的shiro环境就配置好了    */
            
            //取得当前用户
            Subject subject=SecurityUtils.getSubject();
            
            //使用fuwh来进行登陆验证
                    if(!subject.isAuthenticated()) {
                        UsernamePasswordToken token=new UsernamePasswordToken("fuwh","123456");
                        try {
                            subject.login(token);
                            log.info(token.getPrincipal()+"登陆成功!!!");
                            if(subject.hasRole("admin")) {
                                log.info(token.getPrincipal()+"有admin的角色");
                                Permission p1=new WildcardPermission("bumen:*:query");
                                if(subject.isPermitted(p1)) {
                                    log.info(token.getPrincipal()+"有bumen:*:query的权限");
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error("认证失败...");
                        }
                    }
                    subject.logout();
                    
                    log.debug("*****************************************************************");
                    
                    if(!subject.isAuthenticated()) {
                        UsernamePasswordToken token=new UsernamePasswordToken("zhangsan","123");
                        try {
                            subject.login(token);
                            log.info(token.getPrincipal()+"登陆成功!!!");
                            if(subject.hasRole("yuangong")) {
                                log.info(token.getPrincipal()+"有yuangong的角色");
                                Permission p1=new WildcardPermission("bumen:diwubu:query");
                                if(subject.isPermitted(p1)) {
                                    log.info(token.getPrincipal()+"有bumen:diwubu:query的权限");
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error("认证失败...");
                        }
                    }
                    subject.logout();
                    
                    log.debug("*****************************************************************");
                    
                    if(!subject.isAuthenticated()) {
                        UsernamePasswordToken token=new UsernamePasswordToken("lisi","12");
                        try {
                            subject.login(token);
                            log.info(token.getPrincipal()+"登陆成功!!!");
                            if(subject.hasRole("yuangong")) {
                                log.info(token.getPrincipal()+"有yuangong的角色");
                                Permission p1=new WildcardPermission("bumen:diwubu:update");
                                if(subject.isPermitted(p1)) {
                                    log.info(token.getPrincipal()+"有bumen:diwubu:update的权限");
                                }else {
                                    log.info(token.getPrincipal()+"没有bumen:diwubu:update的权限");
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            log.error("认证失败...");
                        }
                    }
                    subject.logout();
        }
    }

    点此查看源码:https://github.com/oukafu/shiro

  • 相关阅读:
    OSCache报错error while trying to flush writer
    html 输入框验证
    Struts2 一张图片引发的bug
    Html 小插件10 即时新闻
    String
    内部类
    多态
    抽象&接口
    继承
    封装
  • 原文地址:https://www.cnblogs.com/zerotomax/p/7436511.html
Copyright © 2011-2022 走看看