• Shiro


     

     例子:

     1 package com.yrg.shirodemo.test;
     2 
     3 import org.apache.shiro.SecurityUtils;
     4 import org.apache.shiro.authc.UsernamePasswordToken;
     5 import org.apache.shiro.mgt.DefaultSecurityManager;
     6 import org.apache.shiro.realm.SimpleAccountRealm;
     7 import org.apache.shiro.subject.Subject;
     8 import org.junit.Before;
     9 import org.junit.Test;
    10 
    11 /**
    12  * 
    13  * @author 74578
    14  *
    15  */
    16 public class AuthenticationTest {
    17     
    18     SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
    19     
    20     @Before
    21     public void addUser() {
    22         simpleAccountRealm.addAccount("Mark", "123456");//初始化一个数据
    23     }
    24     
    25     @Test
    26     public void testAuthentication() {
    27         //1.构建SecurityManager环境
    28         DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
    29         defaultSecurityManager.setRealm(simpleAccountRealm);//将simpleAccountRealm设置到环境中来
    30         //2.主体提交认证
    31         SecurityUtils.setSecurityManager(defaultSecurityManager);//设置Security Manager环境
    32         Subject subject = SecurityUtils.getSubject();//获得主体
    33         
    34         UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");//设置要进行认证的用户
    35         subject.login(token);//    登录,提交认证    
    36         
    37         System.out.println("isAuthenticated():"+subject.isAuthenticated());//判断是否认证成功
    38         
    39         subject.logout();//退出
    40         System.out.println("isAuthenticated():"+subject.isAuthenticated());//判断是否认证成功
    41         
    42         
    43     }
    44 }

     

    package com.yrg.shirodemo.test;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.realm.SimpleAccountRealm;
    import org.apache.shiro.subject.Subject;
    import org.junit.Before;
    import org.junit.Test;
    
    /**
     * 
     * @author 74578
     *
     */
    public class AuthenticationTest {
        
        SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
        
        @Before
        public void addUser() {
            //simpleAccountRealm.addAccount("Mark", "123456");//初始化一个数据
            simpleAccountRealm.addAccount("Mark", "123456","admin","user");//初始化一个数据,赋予一个或多个权限
        }
        
        @Test
        public void testAuthentication() {
            //1.构建SecurityManager环境
            DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
            defaultSecurityManager.setRealm(simpleAccountRealm);//将simpleAccountRealm设置到环境中来
            //2.主体提交认证
            SecurityUtils.setSecurityManager(defaultSecurityManager);//设置Security Manager环境
            Subject subject = SecurityUtils.getSubject();//获得主体
            
            UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");//设置要进行认证的用户
            subject.login(token);//    登录,提交认证    
            
            System.out.println("isAuthenticated():"+subject.isAuthenticated());//判断是否认证成功
            
    //        subject.logout();//退出
    //        System.out.println("isAuthenticated():"+subject.isAuthenticated());//判断是否认证成功
            
            //subject.checkRole("admin");//检查一个权限
            subject.checkRoles("admin","user");//检查多个权限
        }
    }

    SimpleAccountRealm不支持授权

     IniRealmTest:

    package com.yrg.shirodemo.test;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.realm.SimpleAccountRealm;
    import org.apache.shiro.realm.text.IniRealm;
    import org.apache.shiro.subject.Subject;
    import org.junit.Before;
    import org.junit.Test;
    
    public class IniRealmTest {
        
    
        @Test
        public void testAuthentication() {
    
            //创建IniRealm对象
            IniRealm iniRealm = new IniRealm("classpath:user.ini");
            
            //1.构建SecurityManager环境
            DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
            defaultSecurityManager.setRealm(iniRealm);
            //2.主体提交认证
            SecurityUtils.setSecurityManager(defaultSecurityManager);//设置Security Manager环境
            Subject subject = SecurityUtils.getSubject();//获得主体
            
            UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");//设置要进行认证的用户
            subject.login(token);//    登录,提交认证    
            
            System.out.println("isAuthenticated():"+subject.isAuthenticated());//判断是否认证成功
            
            
        }
    }

    user.ini:

    [users]
    Mark=123456

    iniRealm授权:

    user.ini:

    [users]
    Mark=123456,admin
    [roles]
    admin:user:delete,user:insert

    IniRealmTest:

    package com.yrg.shirodemo.test;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.realm.SimpleAccountRealm;
    import org.apache.shiro.realm.text.IniRealm;
    import org.apache.shiro.subject.Subject;
    import org.junit.Before;
    import org.junit.Test;
    
    public class IniRealmTest {
        
    
        @Test
        public void testAuthentication() {
    
            //创建IniRealm对象
            IniRealm iniRealm = new IniRealm("classpath:user.ini");
            
            //1.构建SecurityManager环境
            DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
            defaultSecurityManager.setRealm(iniRealm);
            //2.主体提交认证
            SecurityUtils.setSecurityManager(defaultSecurityManager);//设置Security Manager环境
            Subject subject = SecurityUtils.getSubject();//获得主体
            
            UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");//设置要进行认证的用户
            subject.login(token);//    登录,提交认证    
            
            System.out.println("isAuthenticated():"+subject.isAuthenticated());//判断是否认证成功
            
            subject.checkRole("admin");
            
            //subject.checkPermission("user:insert");
            //subject.checkPermission("user:update");
            subject.checkPermission("user:delete");
        
        }
    }

    JdbcRealm:

    数据库:

    users:

    user_roles:

    roles_permissions:

    导入依赖:

     <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>
        
            <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>

    JdbcRealmTest:

    package com.yrg.shirodemo.test;
    
    import javax.sql.DataSource;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.realm.jdbc.JdbcRealm;
    import org.apache.shiro.realm.text.IniRealm;
    import org.apache.shiro.subject.Subject;
    import org.junit.Test;
    
    import com.alibaba.druid.pool.DruidDataSource;
    
    public class JdbcRealmTest {
        
        DruidDataSource dataSource = new DruidDataSource();
        {
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://localhost:3306/shirotest?serverTimezone=UTC");
            dataSource.setUsername("root");
            dataSource.setPassword("123456");
        }
        
        @Test
        public void testAuthentication() {
    
            //创建JdbcRealm对象
            JdbcRealm jdbcRealm = new JdbcRealm();    
            
            jdbcRealm.setDataSource(dataSource);
        
            //1.构建SecurityManager环境
            DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
            defaultSecurityManager.setRealm(jdbcRealm);
            //2.主体提交认证
            SecurityUtils.setSecurityManager(defaultSecurityManager);//设置Security Manager环境
            Subject subject = SecurityUtils.getSubject();//获得主体
            
            UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");//设置要进行认证的用户
            subject.login(token);//    登录,提交认证    
            
            System.out.println("isAuthenticated():"+subject.isAuthenticated());//判断是否认证成功
        
        }    
            
    }

    添加角色

     JdbcRealmTest:查询权限

    package com.yrg.shirodemo.test;
    
    import javax.sql.DataSource;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.realm.jdbc.JdbcRealm;
    import org.apache.shiro.realm.text.IniRealm;
    import org.apache.shiro.subject.Subject;
    import org.junit.Test;
    
    import com.alibaba.druid.pool.DruidDataSource;
    
    public class JdbcRealmTest {
        
        DruidDataSource dataSource = new DruidDataSource();
        {
            dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
            dataSource.setUrl("jdbc:mysql://localhost:3306/shirotest?serverTimezone=UTC");
            dataSource.setUsername("root");
            dataSource.setPassword("123456");
        }
        
        @Test
        public void testAuthentication() {
    
            //创建JdbcRealm对象
            JdbcRealm jdbcRealm = new JdbcRealm();    
            
            jdbcRealm.setDataSource(dataSource);
            jdbcRealm.setPermissionsLookupEnabled(true);//设置权限开关,只有设置成true才能查询权限
        
      
        //
    1.构建SecurityManager环境 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); defaultSecurityManager.setRealm(jdbcRealm); //2.主体提交认证 SecurityUtils.setSecurityManager(defaultSecurityManager);//设置Security Manager环境 Subject subject = SecurityUtils.getSubject();//获得主体 UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");//设置要进行认证的用户 subject.login(token);// 登录,提交认证 System.out.println("isAuthenticated():"+subject.isAuthenticated());//判断是否认证成功 subject.checkRole("admin"); subject.checkRoles("admin","user"); subject.checkPermission("user:delete"); } }

    自定义sql语句:

    数据库表

    test_user

     test_user_role

     test_role_permission

     代码:

     1 package com.yrg.shirodemo.test;
     2 
     3 import javax.sql.DataSource;
     4 
     5 import org.apache.shiro.SecurityUtils;
     6 import org.apache.shiro.authc.UsernamePasswordToken;
     7 import org.apache.shiro.mgt.DefaultSecurityManager;
     8 import org.apache.shiro.realm.jdbc.JdbcRealm;
     9 import org.apache.shiro.realm.text.IniRealm;
    10 import org.apache.shiro.subject.Subject;
    11 import org.junit.Test;
    12 
    13 import com.alibaba.druid.pool.DruidDataSource;
    14 
    15 public class JdbcRealmTest {
    16     
    17     DruidDataSource dataSource = new DruidDataSource();
    18     {
    19         dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    20         dataSource.setUrl("jdbc:mysql://localhost:3306/shirotest?serverTimezone=UTC");
    21         dataSource.setUsername("root");
    22         dataSource.setPassword("123456");
    23     }
    24     
    25     @Test
    26     public void testAuthentication() {
    27 
    28         //创建JdbcRealm对象
    29         JdbcRealm jdbcRealm = new JdbcRealm();    
    30         
    31         jdbcRealm.setDataSource(dataSource);
    32         jdbcRealm.setPermissionsLookupEnabled(true);//设置权限开关,只有设置成true才能查询权限
    33         
    34         //查询密码
    35         String sql = "select password from test_user where username = ?";
    36         jdbcRealm.setAuthenticationQuery(sql);
    37         
    38         //查询role
    39         String roleSql = "select role_name from test_user_role where username = ?";
    40         jdbcRealm.setUserRolesQuery(roleSql);
    41         
    42         //查询权限
    43         String permission  = "select permissions from test_role_permission where role_name = ?";
    44         jdbcRealm.setPermissionsQuery(permission);
    45         
    46         //1.构建SecurityManager环境
    47         DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
    48         defaultSecurityManager.setRealm(jdbcRealm);
    49         //2.主体提交认证
    50         SecurityUtils.setSecurityManager(defaultSecurityManager);//设置Security Manager环境
    51         Subject subject = SecurityUtils.getSubject();//获得主体
    52         
    53         //UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");//设置要进行认证的用户
    54         UsernamePasswordToken token = new UsernamePasswordToken("xiaoming","654321");
    55         subject.login(token);//    登录,提交认证    
    56         
    57         System.out.println("isAuthenticated():"+subject.isAuthenticated());//判断是否认证成功
    58         
    59         //subject.checkRole("admin");
    60         subject.checkRole("user");
    61 
    62 //        
    63 //        subject.checkRoles("admin","user");
    64 //        
    65         subject.checkPermission("user:delete");
    66     }    
    67         
    68 }

    自定义Realm

    继承:authorizingRealm

    CustomRealm:

    package com.yrg.shirodemo.realm;
    
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    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;
    
    public class CustomRealm extends AuthorizingRealm{
        
        Map<String,String> userMap = new HashMap<String, String>(16);
        {
            userMap.put("Mark","123456");
            super.setName("customRealm");
        }
        /**
         * 做授权
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            
            String username  = (String) principals.getPrimaryPrincipal();
            Set<String> roles = getRolesByUserName(username);
            
            Set<String> permissions = getPermissionByUserName(username);
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            simpleAuthorizationInfo.setStringPermissions(permissions);
            simpleAuthorizationInfo.setRoles(roles);
            return simpleAuthorizationInfo;
        }
        
        private Set<String> getPermissionByUserName(String username) {
            Set<String> sets = new HashSet<String>();
             sets.add("user:delete");
             sets.add("user:add");
            return sets;
        }
    
        private Set<String> getRolesByUserName(String username) {
            Set<String> sets = new HashSet<String>();
             sets.add("admin");
             sets.add("user");
            return sets;
        }
    
        /**
         * 做认证
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            
            //1.从主体传过来的认证信息中,获得用户名
            String username = (String) token.getPrincipal();
            
            //通过用户名到数据库中获取凭证
            String password =getPasswordByUserName(username);
            if(password==null) {
                return null;
            }
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("Mark",password,"customRealm");// 创建一个返回对象
            return authenticationInfo;
        }
    
        /**
         * 模拟数据库
         * @param username
         * @return
         */
        private String getPasswordByUserName(String username) {
            
            return userMap.get(username);
        }
    
    }

    CustomRealmTest:

    package com.yrg.shirodemo.test;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.mgt.DefaultSecurityManager;
    import org.apache.shiro.realm.text.IniRealm;
    import org.apache.shiro.subject.Subject;
    import org.junit.Test;
    
    import com.yrg.shirodemo.realm.CustomRealm;
    
    public class CustomRealmTest {
        
        @Test
        public void testAuthentication() {
    
            //创建CustomRealm对象
            CustomRealm customRealm = new CustomRealm();
            
            //1.构建SecurityManager环境
            DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
            defaultSecurityManager.setRealm(customRealm);
            //2.主体提交认证
            SecurityUtils.setSecurityManager(defaultSecurityManager);//设置Security Manager环境
            Subject subject = SecurityUtils.getSubject();//获得主体
            
            UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");//设置要进行认证的用户
            subject.login(token);//    登录,提交认证    
            
            System.out.println("isAuthenticated():"+subject.isAuthenticated());//判断是否认证成功
            
            subject.checkRole("admin");
            
            subject.checkPermission("user:add");
            //subject.checkPermission("user:update");
            subject.checkPermission("user:delete");
        
        }
    }

    CustomRealm:

    package com.yrg.shirodemo.realm;
    
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    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.crypto.hash.Md5Hash;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    
    public class CustomRealm extends AuthorizingRealm{
        
        Map<String,String> userMap = new HashMap<String, String>(16);
        {
            Md5Hash md5Hash = new Md5Hash("123456","Mark");//"Mark"是盐
            userMap.put("Mark",md5Hash.toString());
            super.setName("customRealm");
        }
        /**
         * 做授权
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            
            String username  = (String) principals.getPrimaryPrincipal();
            Set<String> roles = getRolesByUserName(username);
            
            Set<String> permissions = getPermissionByUserName(username);
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            simpleAuthorizationInfo.setStringPermissions(permissions);
            simpleAuthorizationInfo.setRoles(roles);
            
            return simpleAuthorizationInfo;
        }
        
        private Set<String> getPermissionByUserName(String username) {
            Set<String> sets = new HashSet<String>();
             sets.add("user:delete");
             sets.add("user:add");
            return sets;
        }
    
        private Set<String> getRolesByUserName(String username) {
            Set<String> sets = new HashSet<String>();
             sets.add("admin");
             sets.add("user");
            return sets;
        }
    
        /**
         * 做认证
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            
            //1.从主体传过来的认证信息中,获得用户名
            String username = (String) token.getPrincipal();
            
            //通过用户名到数据库中获取凭证
            String password =getPasswordByUserName(username);
            if(password==null) {
                return null;
            }
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("Mark",password,"customRealm");// 创建一个返回对象
            
            authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("Mark"));//给返回对象设置盐
            return authenticationInfo;
        }
    
        /**
         * 模拟数据库
         * @param username
         * @return
         */
        private String getPasswordByUserName(String username) {
            
            return userMap.get(username);
        }
    
    }

    CustomRealmTest不变

     Shiro集成Spring

    新建shrio-web项目

    导入如下依赖

     <dependencies>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context</artifactId>
              <version>4.1.9.RELEASE</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-webmvc</artifactId>
              <version>4.1.9.RELEASE</version>
          </dependency>
          
          <dependency>
              <groupId>org.apache.shiro</groupId>
              <artifactId>shiro-core</artifactId>
              <version>1.4.0</version>    
          </dependency>
          
          <dependency>
              <groupId>org.apache.shiro</groupId>
              <artifactId>shiro-spring</artifactId>
              <version>1.4.0</version>
          </dependency>
          
          <dependency>
              <groupId>org.apache.shiro</groupId>
              <artifactId>shiro-web</artifactId>
              <version>1.4.0</version>
          </dependency>

        <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.5.2</version>
        </dependency>

        <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.5.2</version>
        </dependency>

      </dependencies>

     创建资源文件

    在resource中新建spring包,创建

    applicationContext.xml:

    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <!-- 扫描有注解的文件 base-package 包路径 -->
        <context:component-scan base-package="com.yrg.shiro">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
        
        <!-- 创建shiro的filter对象
        配置securityManager
        loginUrl:设置登录页面
        unauthorizedUrl:未认证的跳转页面
        过滤器链:从上向下执行
            /login.html = anon 不需要验证可以直接返回
            /subLogin = anon    不需要验证可以直接返回
            /*=    authc:经过认证后才能访问相应的路径 -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager"></property>
            <property name="loginUrl" value="login.html"></property>
            <property name="unauthorizedUrl" value="403.html"></property>
            <property name="filterChainDefinitions">
                <value>
                    /login.html = anon
                    /subLogin = anon
                    /* = authc
                </value>
            
            </property>
        </bean>
        
        <!--     创建SecurityManager对象 
                将realm对象设置到环境中    
        -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="realm"></property>
        </bean>
        
       <!--  创建realm对象 -->
        <bean id = "realm" class="com.yrg.shiro.realm.CustomRealm">
            <property name="credentialsMatcher" ref="credentialsMatcher"></property>
        </bean>
        
        <!-- 创建加密对象 -->
         <bean id = "credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
             <property name="hashAlgorithmName" value="md5"></property>
             <property name="hashIterations" value="1"></property>
         </bean>
    </beans>

    springmvc.xml:

    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.0.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <!--扫描controller-->
        <context:component-scan base-package="com.yrg.shiro.controller" >
          
        </context:component-scan>
    
        <!--默认帮你配置最新的处理器映射器和处理器适配器-->
        <mvc:annotation-driven/>
    
        <mvc:resources location="/" mapping="/*"></mvc:resources>
      
    
       
    </beans>

    在WEB-INF下新建web.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
      <display-name>Shrio_web</display-name>
      <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
      <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
          <listener>
            <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>  
        </listener>
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/applicationContext*.xml</param-value>
      </context-param>
      <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:spring/springmvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.html</welcome-file>
        <welcome-file>default.htm</welcome-file>
        <welcome-file>default.jsp</welcome-file>
      </welcome-file-list>
    </web-app>

    新建一个user的实体类:

    package com.yrg.shiro.vo;
    
    public class User {
    
            private String username;
            private String password;
            public String getUsername() {
                return username;
            }
            public void setUsername(String username) {
                this.username = username;
            }
            public String getPassword() {
                return password;
            }
            public void setPassword(String password) {
                this.password = password;
            }
            
    }

    创建CustomRealm:

    package com.yrg.shiro.realm;
    
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    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.crypto.hash.Md5Hash;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    
    public class CustomRealm extends AuthorizingRealm{
        
        Map<String,String> userMap = new HashMap<String, String>(16);
        {
            Md5Hash md5Hash = new Md5Hash("123456","Mark");//"Mark"是盐
            userMap.put("Mark",md5Hash.toString());
            super.setName("customRealm");
        }
        /**
         * 做授权
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            
            String username  = (String) principals.getPrimaryPrincipal();
            Set<String> roles = getRolesByUserName(username);
            
            Set<String> permissions = getPermissionByUserName(username);
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            simpleAuthorizationInfo.setStringPermissions(permissions);
            simpleAuthorizationInfo.setRoles(roles);
            
            return simpleAuthorizationInfo;
        }
        
        private Set<String> getPermissionByUserName(String username) {
            Set<String> sets = new HashSet<String>();
             sets.add("user:delete");
             sets.add("user:add");
            return sets;
        }
    
        private Set<String> getRolesByUserName(String username) {
            Set<String> sets = new HashSet<String>();
             sets.add("admin");
             sets.add("user");
            return sets;
        }
    
        /**
         * 做认证
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            
            //1.从主体传过来的认证信息中,获得用户名
            String username = (String) token.getPrincipal();
            
            //通过用户名到数据库中获取凭证
            String password =getPasswordByUserName(username);
            if(password==null) {
                return null;
            }
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("Mark",password,"customRealm");// 创建一个返回对象
            
            authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("Mark"));
            return authenticationInfo;
        }
    
        /**
         * 模拟数据库
         * @param username
         * @return
         */
        private String getPasswordByUserName(String username) {
            
            return userMap.get(username);
        }
    
    }

    创建一个Controller控制器

    UserController:

    package com.yrg.shiro.controller;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.yrg.shiro.vo.User;
    
    @Controller
    public class UserController {
        
        
        @RequestMapping(value = "/subLogin",method = RequestMethod.POST)
        @ResponseBody
        public String subLogin(User user) {
        //    SecurityUtils.setSecurityManager(securityManager);
            Subject subject  = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
            try {
                subject.login(token);
            } catch (AuthenticationException e) {
                return e.getMessage();
            }
            return "Login Success";
        }
    }

    创建3个页面,login.html, 403.html,index.html

    login.html:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>login</title>
    </head>
    <body>
        <form action="subLogin" method="post">
            <input type="text" name="username" placeholder="username"/></br></br>
            <input  type="text" name="password" placeholder="password"/></br></br>
            <button type="submit" name="submit" >submit</button>
        </form>
    </body>
    </html>

    403.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    
    </body>
    </html>

    index.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>HelloWorld</title>
    </head>
    <body>
        <h2>Hello World</h2>
    </body>
    <script type="text/javascript">
    
    </script>
    </html>

    然后执行程序

    Shiro集成Spring-从数据库中获取数据

     在上面的基础上引入如下依赖:

         <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.16</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.16</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>4.1.9.RELEASE</version>
            </dependency>

    创建applicationContext-dao.xml

    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    
            <bean id = "dataSource" class="com.alibaba.druid.pool.DruidDataSource">
                <property name="name" value="com.mysql.cj.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://localhost:3306/shirotest?serverTimezone=UTC"></property>
                <property name="username" value="root"></property>
                <property name="password" value="123456"></property>
             </bean>
            
            <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                <property name="dataSource" ref="dataSource"></property>
            </bean>
    </beans>

    创建CustomRealm2

    package com.yrg.shiro.realm;
    
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import javax.annotation.Resource;
    
    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.crypto.hash.Md5Hash;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import com.yrg.shiro.dao.IUserDao;
    import com.yrg.shiro.vo.User;
    
    public class CustomRealm2 extends AuthorizingRealm{
        
        @Resource
        private  IUserDao userdao;
        /**
         * 做授权
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            
            String username  = (String) principals.getPrimaryPrincipal();
            Set<String> roles = getRolesByUserName(username);
            
            Set<String> permissions = getPermissionByUserName(username);
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            simpleAuthorizationInfo.setStringPermissions(permissions);
            simpleAuthorizationInfo.setRoles(roles);
            
            return simpleAuthorizationInfo;
        }
        
        private Set<String> getPermissionByUserName(String username) {
            //    List<String> list = userdao.queryPermissionByUserName(username);
            Set<String> sets = new HashSet<String>();
             sets.add("user:delete");
             sets.add("user:add");
            return sets;
        }
    
        private Set<String> getRolesByUserName(String username) {
            List<String> list = userdao.queryRolesByUserName(username);
            Set<String> sets = new HashSet<String>(list);
            return sets;
        }
    
        /**
         * 做认证
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            
            //1.从主体传过来的认证信息中,获得用户名
            String username = (String) token.getPrincipal();
            
            //通过用户名到数据库中获取凭证
            String password =getPasswordByUserName(username);
            if(password==null) {
                return null;
            }
            System.out.println(password);
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,"customRealm2");// 创建一个返回对象
            
            authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(username));
            return authenticationInfo;
        }
    
        /**
         * 模拟数据库
         * @param username
         * @return
         */
        private String getPasswordByUserName(String username) {
            User user = userdao.getUserByUserName(username);
            if(user==null) {
                return null;
            }
            return user.getPassword();
        }
        
        public static void main(String[] args) {
            Md5Hash md5Hash = new Md5Hash("123456","Mark");
            System.out.println(md5Hash.toString());
        }
    }

    修改applications.xml

    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <!-- 扫描有注解的文件 base-package 包路径 -->
        <context:component-scan base-package="com.yrg.shiro">
            <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        </context:component-scan>
        
        <!-- 创建shiro的filter对象
        配置securityManager
        loginUrl:设置登录页面
        unauthorizedUrl:未认证的跳转页面
        过滤器链:从上向下执行
            /login.html = anon 不需要验证可以直接返回
            /subLogin = anon    不需要验证可以直接返回
            /*=    authc:经过认证后才能访问相应的路径 -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager"></property>
            <property name="loginUrl" value="login.html"></property>
            <property name="unauthorizedUrl" value="403.html"></property>
            <property name="filterChainDefinitions">
                <value>
                    /login.html = anon
                    /subLogin = anon
                    /* = authc
                </value>
            
            </property>
        </bean>
        
        <!--     创建SecurityManager对象 
                将realm对象设置到环境中    
        -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="realm"></property>
        </bean>
        
       <!--  创建realm对象 -->
        <bean id = "realm" class="com.yrg.shiro.realm.CustomRealm2">
            <property name="credentialsMatcher" ref="credentialsMatcher"></property>
        </bean>
        
        <!-- 创建加密对象 -->
         <bean id = "credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
             <property name="hashAlgorithmName" value="md5"></property>
             <property name="hashIterations" value="1"></property>
         </bean>
    
    
    </beans>

    修改UserController

    package com.yrg.shiro.controller;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.yrg.shiro.vo.User;
    
    @Controller
    public class UserController {
        
        
        @RequestMapping(value = "/subLogin",method = RequestMethod.POST)
        @ResponseBody
        public String subLogin(User user) {
        //    SecurityUtils.setSecurityManager(securityManager);
            Subject subject  = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
            try {
                subject.login(token);
            } catch (AuthenticationException e) {
                return e.getMessage();
            }
            if(subject.hasRole("admin")) {
                return "hava admin";
            }
            else {
                return "don't have admin";
            }
            //return "Login Success";
        }
    }

    运行项目即可

    通过注解配置设置授权

    导入依赖

            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.8.9</version>
            </dependency>            

     在applicationContext中配置

    <aop:config proxy-target-class="true"></aop:config>
        <bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager"></property>
        </bean>

    在springmvc.xml

    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.0.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
    
        <!--扫描controller-->
        <context:component-scan base-package="com.yrg.shiro.controller" >
          
        </context:component-scan>
    
        <!--默认帮你配置最新的处理器映射器和处理器适配器-->
        <mvc:annotation-driven/>
        
        
        <mvc:resources location="/" mapping="/*"></mvc:resources>
        
            <aop:config proxy-target-class="true"></aop:config>
        <bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager"></property>
        </bean>
      
    
    </beans>

    在UserController后添加

       @RequiresRoles("admin") //需要admin的权限才能访问testrole方法
        @RequestMapping(value="/testRole",method = RequestMethod.GET)
        @ResponseBody
        public String testRole() {
            return "testrole success";
        }
        
        //@RequiresPermissions("xxx")//可以添加数组形式
        @RequiresRoles("admin1")//需要admin1的权限才能访问testrelo1方法
        @RequestMapping(value="/testRole1",method = RequestMethod.GET)
        @ResponseBody
        public String testRole1() {
            return "testrole1 success";
        }

    修改UserController

    package com.yrg.shiro.controller;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.annotation.RequiresPermissions;
    import org.apache.shiro.authz.annotation.RequiresRoles;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.yrg.shiro.vo.User;
    
    @Controller
    public class UserController {
        
        
        @RequestMapping(value = "/subLogin",method = RequestMethod.POST)
        @ResponseBody
        public String subLogin(User user) {
        //    SecurityUtils.setSecurityManager(securityManager);
            Subject subject  = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
            try {
                subject.login(token);
            } catch (AuthenticationException e) {
                return e.getMessage();
            }
            if(subject.hasRole("admin")) {
                return "hava admin";
            }
            else {
                return "don't have admin";
            }
            //return "Login Success";
        }
        
        //@RequiresRoles("admin") //需要admin的权限才能访问testrole方法
        @RequestMapping(value="/testRole",method = RequestMethod.GET)
        @ResponseBody
        public String testRole() {
            return "testrole success";
        }
        
        //@RequiresPermissions("xxx")//可以添加数组形式
        //@RequiresRoles("admin1")//需要admin1的权限才能访问testrelo1方法
        @RequestMapping(value="/testRole1",method = RequestMethod.GET)
        @ResponseBody
        public String testRole1() {
            return "testrole1 success";
        }
        
        @RequestMapping(value="/testPerms",method = RequestMethod.GET)
        @ResponseBody
        public String testPerms() {
            return "testPerms success";
        }
        @RequestMapping(value="/testPerms1",method = RequestMethod.GET)
        @ResponseBody
        public String testPerms1() {
            return "testPerms1 success";
        }
    }

    修改applicationContext.xml

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager"></property>
            <property name="loginUrl" value="login.html"></property>
            <property name="unauthorizedUrl" value="403.html"></property>
            <property name="filterChainDefinitions">
                <value>
                    /login.html = anon
                    /subLogin = anon
                    /testRole = roles["admin"]
                    /testRole1 = roles["admin","admin1"]
                    /testPerms = perms["user:delete"]
                    /testPerms1 = perms["user:delete",""user:update"]
                    /* = authc
                </value>
            
            </property>
        </bean>

    运行程序,登录后访问相关网址,就能查看结果

    自定义Filter

     创建RolesOrFilter继承AuthorizationFilter

    package com.yrg.shiro.filter;
    
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.web.filter.authz.AuthorizationFilter;
    
    /**
     * <p>ProjectName: Shrio_web</p>
     * <p>ClassName:RolesOrFilter</p>
     * @author yangrg
     * @time 2019年11月29日 上午10:29:47
     */
    public class RolesOrFilter extends AuthorizationFilter{
    
        
        @Override
        protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
                throws Exception {
            
            Subject subject = getSubject(request, response);
            String[] roles = (String[]) mappedValue;
            if(roles == null||roles.length ==0) {
                return false;
            }
            for(String role:roles) {
                if(subject.hasRole(role)){
                    return true;
                }
            }
            
            return false;
        }
    }

    在applicationContext中添加如下

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager"></property>
            <property name="loginUrl" value="login.html"></property>
            <property name="unauthorizedUrl" value="403.html"></property>
            <property name="filterChainDefinitions">
                <value>
                    /login.html = anon
                    /subLogin = anon
                    <!-- /testRole = roles["admin"]
                    /testRole1 = roles["admin","admin1"]
                    /testPerms = perms["user:delete"]
                    /testPerms1 = perms["user:delete",""user:update"] -->
                    
                    /testRole =roles["admin","admin1"]
                    /testRole1 = rolesOr["admin","admin1"]
                    /* = authc
                </value>
            </property>
            <property name="filters">
                <util:map>
                    <entry key="rolesOr" value-ref="rolesOrFilter"></entry>
                </util:map>
            </property>
        </bean>
        
        <!-- 创建自定义的filter -->
        <bean class="com.yrg.shiro.filter.RolesOrFilter" id="rolesOrFilter"></bean>

    运行访问testRole和testRole1查看区别

     

     添加如下依赖

         <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>2.8.0</version>
            </dependency>

    创建ApplicationContext-redis.xml配置redis的连接

    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://www.springframework.org/schema/beans"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx.xsd"
    > <bean class="redis.clients.jedis.JedisPool" id="jedisPool"> <constructor-arg ref="jedisPoolConfig"></constructor-arg> <constructor-arg value="127.0.0.1"></constructor-arg> <constructor-arg value="6379"></constructor-arg> </bean> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"></bean> </bean

    创建JedisUtiils实现redis的一些基本操作

    /**   
    * @Title: JedisUtils.java 
    * @Package com.yrg.shiro.utils 
    * @Description: TODO(用一句话描述该文件做什么) 
    * @author yangrg  
    * @date 2019年11月29日 下午4:27:57 
    * @version V1.0   
    */
    package com.yrg.shiro.utils;
    
    import java.util.Set;
    
    import javax.annotation.Resource;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import jdk.nashorn.internal.ir.annotations.Reference;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    
    /** 
    * @ClassName: JedisUtils 
    * @Description: TODO(这里用一句话描述这个类的作用) 
    * @author yangrg 
    * @date 2019年11月29日 下午4:27:57 
    *  
    */
    @Component
    public class JedisUtils {
    
        @Autowired
        private JedisPool jedisPool;
    
        private Jedis getResource() {
            return jedisPool.getResource();
        }
         
        /**
        * @Title: set 
        * @Description: TODO(这里用一句话描述这个方法的作用) 
        * @param @param key
        * @param @param value
        * @param @return     
        * @return byte[]    
        * @throws
         */
        public byte[] set(byte[] key, byte[] value) {
            Jedis jedis = getResource();
            try {
                jedis.set(key, value);
                return value;
            } finally {
                jedis.close();
            }
        }
        
        /** 
        * @Title: expire 
        * @Description: TODO(这里用一句话描述这个方法的作用) 
        * @param @param key
        * @param @param i     
        * @return void    
        * @throws 
        */
        public void expire(byte[] key, int i) {
            Jedis jedis = getResource();
            try {
                jedis.expire(key, i);
            }finally {
                jedis.close();
            }
        }
    
        /** 
        * @Title: get 
        * @Description: TODO(这里用一句话描述这个方法的作用) 
        * @param @param value
        * @param @return     
        * @return byte []    
        * @throws 
        */
        public byte[] get(byte[] key) {
            
            Jedis jedis = getResource();
            try {
                
                return jedis.get(key);
            } finally {
                jedis.close();
            }
        }
    
        /** 
        * @Title: del 
        * @Description: TODO(这里用一句话描述这个方法的作用) 
        * @param @param key     
        * @return void    
        * @throws 
        */
        public void del(byte[] key) {
            Jedis jedis = getResource();
            try {
                jedis.del(key);
            } finally {
                jedis.close();
            }
        }
    
        /** 
        * @Title: keys 
        * @Description: TODO(这里用一句话描述这个方法的作用) 
        * @param @param sHIRO_SESSION_PREFIX
        * @param @return     
        * @return Set<byte []>    
        * @throws 
        */
        public Set<byte[]> keys(String sHIRO_SESSION_PREFIX) {
            Jedis jedis = getResource();
            try {
                
                return jedis.keys((sHIRO_SESSION_PREFIX+"*").getBytes());
            } finally {
                jedis.close();
            }
        }
        
    }

    创建RedisSessionDao

    /**   
    * @Title: RedisSessionDao.java 
    * @Package com.yrg.shiro.session 
    * @Description: TODO(用一句话描述该文件做什么) 
    * @author yangrg  
    * @date 2019年11月29日 下午3:26:06 
    * @version V1.0   
    */
    package com.yrg.shiro.session;
    
    import java.io.Serializable;
    import java.util.Collection;
    import java.util.HashSet;
    import java.util.Set;
    
    import javax.annotation.Resource;
    
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.UnknownSessionException;
    import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
    import org.springframework.util.SerializationUtils;
    
    import com.yrg.shiro.utils.JedisUtils;
    
    import jdk.nashorn.internal.ir.annotations.Reference;
    
    /** 
    * @ClassName: RedisSessionDao 
    * @Description: TODO(这里用一句话描述这个类的作用) 
    * @author yangrg 
    * @date 2019年11月29日 下午3:26:06 
    *  
    */
    public class RedisSessionDao extends AbstractSessionDAO{
    
        @Resource
        private JedisUtils jedisUtils;
        
        private String SHIRO_SESSION_PREFIX ="yrg session";
        
        private  byte[] getkey(String key) {
            return (SHIRO_SESSION_PREFIX+key).getBytes();
        }
        
        private void savesession(Session session) {
            if(session!= null&&session.getId()!=null) {
                byte[] key = getkey(session.getId().toString());
                byte[] value = SerializationUtils.serialize(session);
                jedisUtils.set(key,value);
                jedisUtils.expire(key,600 );
            }
        }
        
        @Override
        protected Serializable doCreate(Session session) {
            Serializable sessionId = generateSessionId(session);//通过session获取session id
            assignSessionId(session, sessionId);//将sessionid和session进行捆绑
            savesession(session);
            return sessionId;
        }
        
        @Override
        protected Session doReadSession(Serializable sessionId) {
            if(sessionId == null) {
                return null;
            }
            byte[] key = getkey(sessionId.toString());
            byte[] value = jedisUtils.get(key);
                
            return (Session) SerializationUtils.deserialize(value);
        }
        
        public void update(Session session) throws UnknownSessionException {
        
                savesession(session);
        
        }
    
        public void delete(Session session) {
            if(session ==null || session.getId() ==null) {
                return;
            }
            byte[] key =getkey(session.getId().toString());
            jedisUtils.del(key);
        }
    
        public Collection<Session> getActiveSessions() {
            Set<byte[]> keys = jedisUtils.keys(SHIRO_SESSION_PREFIX);
            Set<Session> sessions  = new HashSet<Session>();
            if(CollectionUtils.isEmpty(keys)) {
                return sessions;
            }
            for(byte[] key:keys) {
                Session session =(Session)SerializationUtils.deserialize(jedisUtils.get(key));
                sessions.add(session);
            }
            return sessions;
        }
    }

    在applicationContext中配置添加

    <!--     创建SecurityManager对象 
                将realm对象设置到环境中    
        -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="realm"></property>
            <property name="sessionManager" ref="sessionManager"></property>
        </bean>
    
        <bean class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager" id="sessionManager">
                <property name="sessionDAO" ref="redisSessionDao"></property>
            </bean>
            
            <bean class="com.yrg.shiro.session.RedisSessionDao" id="redisSessionDao"></bean>

    运行程序,查看redis,可以看到里面多了数据

    多次访问redis的问题:

    自定义SessionManager

    /**   
    * @Title: CustomSessionManager.java 
    * @Package com.yrg.shiro.session 
    * @Description: TODO(用一句话描述该文件做什么) 
    * @author yangrg  
    * @date 2019年11月30日 下午9:07:35 
    * @version V1.0   
    */
    package com.yrg.shiro.session;
    
    import java.io.Serializable;
    
    import javax.servlet.ServletRequest;
    
    import org.apache.shiro.session.Session;
    import org.apache.shiro.session.UnknownSessionException;
    import org.apache.shiro.session.mgt.SessionKey;
    import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
    import org.apache.shiro.web.session.mgt.WebSessionKey;
    
    /** 
    * @ClassName: CustomSessionManager 
    * @Description: TODO 从request中读取,不要每次都从redis中读取
    * @author yangrg 
    * @date 2019年11月30日 下午9:07:35 
    *  
    */
    public class CustomSessionManager extends DefaultWebSessionManager {
        
        @Override
        protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
            Serializable sessionId = getSessionId(sessionKey); //获取sessionId
            ServletRequest request = null;
            if(sessionKey instanceof WebSessionKey) {//判断sessionKey是否为WebSessinKey
                request = ((WebSessionKey)sessionKey).getServletRequest(); //从sessionKey中获取request
            }
            //request中获取session
            if(request !=null && sessionId !=null) {
            Session session= (Session) request.getAttribute(sessionId.toString());//从request中获取session
                if(session!=null) {
                    return session;
                }
            }
            //从redis中获取session
            Session session = super.retrieveSession(sessionKey);
            if(request!=null && sessionId !=null) {
                request.setAttribute(sessionId.toString(), session);//将session设置到session中
            }
            return session;
        }
    }

    修改applicationContext

    <bean class="com.yrg.shiro.session.CustomSessionManager" id="sessionManager">
                <property name="sessionDAO" ref="redisSessionDao"></property>
            </bean>

     创建RedisCache

    /**   
    * @Title: RedisCache.java 
    * @Package com.yrg.shiro.cache 
    * @Description: TODO(用一句话描述该文件做什么) 
    * @author yangrg  
    * @date 2019年11月30日 下午10:34:25 
    * @version V1.0   
    */
    package com.yrg.shiro.cache;
    
    import java.util.Collection;
    import java.util.Set;
    
    import javax.annotation.Resource;
    
    import org.apache.shiro.cache.Cache;
    import org.apache.shiro.cache.CacheException;
    import org.springframework.stereotype.Component;
    import org.springframework.util.SerializationUtils;
    
    import com.yrg.shiro.utils.JedisUtils;
    
    import redis.clients.util.JedisURIHelper;
    
    
    /** 
    * @ClassName: RedisCache 
    * @Description: TODO(这里用一句话描述这个类的作用) 
    * @author yangrg 
    * @date 2019年11月30日 下午10:34:25 
    *  
    */
    
    @Component
    public class RedisCache<K,V > implements Cache<K, V> {
    
        @Resource
        private JedisUtils jedisUtils;
        
        private final String CACHE_PREFIX = "yrg-cache:";
        
        //获取key
        private byte[] getkey(K k) {
            if(k instanceof String) {
                return (CACHE_PREFIX+k).getBytes();
            }
            return SerializationUtils.serialize(k);
        }
        
        public V get(K arg0) throws CacheException {
            System.out.println("从redis中得到数据");
            byte[] value = jedisUtils.get(getkey(arg0));
            if(value!=null) {
                return (V) SerializationUtils.deserialize(value);
            }
            return null;
        }
        
        public V put(K arg0, V arg1) throws CacheException {
            byte[] key =getkey(arg0);
            byte[] value =SerializationUtils.serialize(arg1);
            jedisUtils.set(key, value);
            jedisUtils.expire(key, 600);
            return arg1;
        }
        
        public V remove(K arg0) throws CacheException {
            byte[] key = getkey(arg0);
            byte[] value = jedisUtils.get(key);
            jedisUtils.del(key);
            if(value != null) {
                return (V) SerializationUtils.deserialize(value);
            }
            return null;
        }
        
        public void clear() throws CacheException {
            
        }
        
        public int size() {
            
            return 0;
        }
    
        public Set<K> keys() {
            
            return null;
        }
    
        public Collection<V> values() {
            
            return null;
        }
    
    }

    创建RedisManager

    /**   
    * @Title: RedisCacheManager.java 
    * @Package com.yrg.shiro.cache 
    * @Description: TODO(用一句话描述该文件做什么) 
    * @author yangrg  
    * @date 2019年11月30日 下午10:02:32 
    * @version V1.0   
    */
    package com.yrg.shiro.cache;
    
    import javax.annotation.Resource;
    
    import org.apache.shiro.cache.Cache;
    import org.apache.shiro.cache.CacheException;
    import org.apache.shiro.cache.CacheManager;
    
    /** 
    * @ClassName: RedisCacheManager 
    * @Description: TODO(这里用一句话描述这个类的作用) 
    * @author yangrg 
    * @date 2019年11月30日 下午10:02:32 
    *  
    */
    public class RedisCacheManager implements CacheManager{
    
        @Resource
        private RedisCache redisCache;
        
        public <K, V> Cache<K, V> getCache(String arg0) throws CacheException {
            
            return redisCache;
        }
    
    }

    修改applicationContext

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="realm"></property>
            <property name="sessionManager" ref="sessionManager"></property>
            <property name="cacheManager" ref="cacheManager"></property>
        </bean>
    
    <bean class="com.yrg.shiro.cache.RedisCacheManager" id="cacheManager"></bean>

    运行程序观察控制台

     

     在applicationContext中修改,

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="realm"></property>
            <property name="sessionManager" ref="sessionManager"></property>
            <property name="cacheManager" ref="cacheManager"></property>
            <property name="rememberMeManager" ref="cookieRememberMeManager"></property>
        </bean>
    <bean class="org.apache.shiro.web.mgt.CookieRememberMeManager" id="cookieRememberMeManager">
                <property name="cookie" ref="cookie"></property>
            </bean>
        
            <bean class="org.apache.shiro.web.servlet.SimpleCookie" id="cookie">
                <constructor-arg value="rememberMe"></constructor-arg>
                <property name="maxAge" value="600"></property>
            </bean>

    在login.html中添加

        <input type="checkbox" name="rememberMe"/>记住我<br>

    在实体类User添加boolean属性的rememberMe,和set和get方法

    在UserController添加

    package com.yrg.shiro.controller;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.annotation.RequiresPermissions;
    import org.apache.shiro.authz.annotation.RequiresRoles;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.yrg.shiro.vo.User;
    
    @Controller
    public class UserController {
        
        
        @RequestMapping(value = "/subLogin",method = RequestMethod.POST)
        @ResponseBody
        public String subLogin(User user) {
        //    SecurityUtils.setSecurityManager(securityManager);
            Subject subject  = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
            try {
                token.setRememberMe(user.isRemermberMe());
                subject.login(token);
            } catch (AuthenticationException e) {
                return e.getMessage();
            }
            if(subject.hasRole("admin")) {
                return "hava admin";
            }
            else {
                return "don't have admin";
            }
            //return "Login Success";
        }
        
        //@RequiresRoles("admin") //需要admin的权限才能访问testrole方法
        @RequestMapping(value="/testRole",method = RequestMethod.GET)
        @ResponseBody
        public String testRole() {
            return "testrole success";
        }
        
        //@RequiresPermissions("xxx")//可以添加数组形式
        //@RequiresRoles("admin1")//需要admin1的权限才能访问testrelo1方法
        @RequestMapping(value="/testRole1",method = RequestMethod.GET)
        @ResponseBody
        public String testRole1() {
            return "testrole1 success";
        }
        
        @RequestMapping(value="/testPerms",method = RequestMethod.GET)
        @ResponseBody
        public String testPerms() {
            return "testPerms success";
        }
        @RequestMapping(value="/testPerms1",method = RequestMethod.GET)
        @ResponseBody
        public String testPerms1() {
            return "testPerms1 success";
        }
    }

    运行程序查看浏览器开发者工具的cookie

  • 相关阅读:
    CF-1328 F. Make k Equal
    CF-1328 E. Tree Queries
    USACO_1.1_Greedy_Gift_Givers_(模拟+水题)
    USACO_1.1_Your_Ride_Is_Here_(字符串+水题)
    第3章 文件系统
    BZOJ_1629_[Usaco2007_Demo]_Cow_Acrobats_(贪心)
    BZOJ_1628_[Usaco2007_Demo]_City_skyline_(单调栈)
    BZOJ_1030_[JSOI2007]_文本生成器_(AC自动机+DP)
    BZOJ_1029_[JSOI2007]_建筑抢修_(贪心+优先队列)
    BZOJ_1028_[JSOI2007]_麻将_(模拟+贪心)
  • 原文地址:https://www.cnblogs.com/godyrg/p/11956224.html
Copyright © 2020-2023  润新知