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

 

 

posted @ 2019-12-01 00:33  GodYrg  Views(593)  Comments(0)    收藏  举报