例子:
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