shiro与spring Secuity比较:
1 简单灵活
2 科托离spring
3 粒度较粗
spring Secuity与之相反,同时它也是又shiro开发
shiro认证过程:
1 创建secrityManger
2 主体提交认证
3 securityManger认证
4 Realm验证
5 Authenticor认证
代码:
package com.imooc.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 fusiping
* 2018年11月23日
*/
public class AuthenticationTest {
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
@Before
public void addUser() {
simpleAccountRealm.addAccount("Mark","123456");
}
@Test
public void testAuthentication() {
//1.构建securityManage环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
//设置secutityManager环境
SecurityUtils.setSecurityManager(defaultSecurityManager);
//2.主体提交认证请求
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");
subject.login(token);
//结果:isAuthenticated:true
System.out.println("isAuthenticated:"+subject.isAuthenticated());
subject.logout();
//结果:isAuthenticated:false
System.out.println("isAuthenticated:"+subject.isAuthenticated());
}
}
shiro授权:
1 创建SecurityManage
2 主体授权
3 securitymanager授权
4 authorizer授权
5 Realm获取角色权限数据
代码:
package com.imooc.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 fusiping
* 2018年11月23日
*/
public class AuthenticationTest {
SimpleAccountRealm simpleAccountRealm = new SimpleAccountRealm();
@Before
public void addUser() {
simpleAccountRealm.addAccount("Mark","123456","admin");
}
/**
* 授权
*/
@Test
public void testAuthorizer() {
//1.构建securityManage环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
//设置secutityManager环境
SecurityUtils.setSecurityManager(defaultSecurityManager);
//2.主体提交认证请求
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");
subject.login(token);
//结果:isAuthenticated:true
System.out.println("isAuthenticated:"+subject.isAuthenticated());
//没有抛出异常,说明验证成功
subject.checkRole("admin");
}
}
shiro自定义Realm
内置Realm:IniRealm,JdbcRealm
package com.imooc.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;public class IniRealmTest {
@Test
public void testIniRealmr() {
//自定义
IniRealm iniRealm = new IniRealm("classpath:user.ini");
//1.构建securityManage环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(iniRealm);
//设置secutityManager环境
SecurityUtils.setSecurityManager(defaultSecurityManager);
//2.主体提交认证请求
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("Mark","123456");
subject.login(token);
//结果:isAuthenticated:true
System.out.println("isAuthenticated:"+subject.isAuthenticated());
subject.checkRole("user1");
subject.checkPermission("user:update");
}
}
user.ini文件:
[users]
Mark=123456,admin,user1
[roles]
admin=user:delete
user1=user:update
jdbcRealm实例:
package com.imooc.test;
import javax.swing.JScrollBar;
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.subject.Subject;
import org.junit.Test;import com.alibaba.druid.pool.DruidDataSource;
public class JdbcRealmTest {
DruidDataSource dataSource = new DruidDataSource();
{
dataSource.setUrl("jdbc:mysql://localhost:3333/test1");
dataSource.setUsername("test1");
dataSource.setPassword("fsp648734!");
}@Test
public void testIniRealmr() {
JdbcRealm jdbcRealm = new JdbcRealm();
jdbcRealm.setDataSource(dataSource);
//使用jdbcRealm必须设置开关为true,默认为false,否则不能查询权限数据
jdbcRealm.setPermissionsLookupEnabled(true);
//自定义认证查询语句
//jdbcRealm.setAuthenticationQuery("authenticationQuery");
//自定义权限查询语句
//jdbcRealm.setPermissionsQuery("permissionsQuery");
//自定义角色查询语句
//jdbcRealm.setUserRolesQuery("userRolesQuery");
//1.构建securityManage环境
/*
* 默认的查询语句:
protected static final String DEFAULT_AUTHENTICATION_QUERY = "select password from users where username = ?";
protected static final String DEFAULT_SALTED_AUTHENTICATION_QUERY = "select password, password_salt from users where username = ?";protected static final String DEFAULT_USER_ROLES_QUERY = "select role_name from user_roles where username = ?";
*
protected static final String DEFAULT_PERMISSIONS_QUERY = "select permission from roles_permissions where role_name = ?";*/
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(jdbcRealm);
//设置secutityManager环境
SecurityUtils.setSecurityManager(defaultSecurityManager);
//2.主体提交认证请求
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("fusiping","123456");
subject.login(token);
//结果:isAuthenticated:true
System.out.println("isAuthenticated:"+subject.isAuthenticated());
subject.checkRole("admin");
subject.checkPermission("user:delete");
}
}
默认的sql语句:
对应的数据库表:
CREATE TABLE `roles_permissions` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
`permission` varchar(32) NOT NULL COMMENT '权限',
`role_name` varchar(64) NOT NULL COMMENT '角色',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='角色-权限';
CREATE TABLE `user_roles` (
`id` int(11) NOT NULL COMMENT '编号',
`username` varchar(255) NOT NULL COMMENT '用户名',
`role_name` varchar(255) NOT NULL COMMENT '角色',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='shiro用户表';
CREATE TABLE `users` (
`id` int(8) NOT NULL AUTO_INCREMENT COMMENT '主键自增',
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(50) NOT NULL COMMENT '密码',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COMMENT='用户表';
自定义Realm:
package com.imooc.shrio.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;/**自定义
* @author fusiping
* 2018年11月23日
*/
public class CustomRealm extends AuthorizingRealm{
//模拟数据库查询
Map<String, String> map = new HashMap<String, String>(16);
{
map.put("fusiping", "123456");
super.setName("customRealm");
}/* 用来做授权
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userName = (String) principals.getPrimaryPrincipal();
//从数据库或者从缓存中获取角色数据
Set<String> roles = getRolesByUserName(userName);
//通过用户从从数据库或者从缓存中获取权限数据
Set<String> permissions = getPermissionsByUserName(userName);
SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
simpleAuthenticationInfo.setStringPermissions(permissions);
simpleAuthenticationInfo.setRoles(roles);
return simpleAuthenticationInfo;
}/**模拟从数据库或缓存中获取权限数据
* @param userName
* @return
*/
private Set<String> getPermissionsByUserName(String userName) {
Set<String> permissions = new HashSet<String>();
permissions.add("user:delete");
permissions.add("user:add");
return permissions;
}/**模拟数据查询
* @param userName
* @return
*/
private Set<String> getRolesByUserName(String userName) {
Set<String> roles = new HashSet<String>();
roles.add("admin");
roles.add("user");
return roles;
}/* 用来做认证
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//1.从主体传过来的认证信息中,获取用户名
String userName = (String) token.getPrincipal();
//2.通过用户名找到数据库中获取凭证
String password = getPasswordByUserName(userName);
if (password == null) {
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("fusiping",password,"customRealm");
return authenticationInfo;
}/**模拟数据库查询凭证
* @param userName
* @return
*/
private String getPasswordByUserName(String userName) {
return map.get(userName);
}
}
测试类CustomRealmTest :
package com.imooc.test;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;import com.imooc.shrio.realm.CustomRealm;
/**测试
* @author fusiping
* 2018年11月23日
*/
public class CustomRealmTest {@Test
public void testCustomRealm() {
//自定义
CustomRealm customRealm = new CustomRealm();
//1.构建securityManage环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(customRealm);
//设置secutityManager环境
SecurityUtils.setSecurityManager(defaultSecurityManager);
//2.主体提交认证请求
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("fusiping","123456");
subject.login(token);
//结果:isAuthenticated:true
System.out.println("isAuthenticated:"+subject.isAuthenticated());
subject.checkRole("admin");
subject.checkPermission("user:delete");
}
}
shiro加密:
shiro散列配置:
1 hashedCreadentialsMatcher
2 自定义Realm中使用散列
3 盐的使用
package com.imooc.shrio.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;/**自定义
* @author fusiping
* 2018年11月23日
*/
public class CustomRealm extends AuthorizingRealm{
//模拟数据库查询
Map<String, String> map = new HashMap<String, String>(16);
{
map.put("fusiping", "cc2bf701edeca9268997bab3f5b6527d");//123456,Md5加盐“fusiping”,加密后e10adc3949ba59abbe56e057f20f883e
super.setName("customRealm");
}/* 用来做授权
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userName = (String) principals.getPrimaryPrincipal();
//从数据库或者从缓存中获取角色数据
Set<String> roles = getRolesByUserName(userName);
//通过用户从从数据库或者从缓存中获取权限数据
Set<String> permissions = getPermissionsByUserName(userName);
SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
simpleAuthenticationInfo.setStringPermissions(permissions);
simpleAuthenticationInfo.setRoles(roles);
return simpleAuthenticationInfo;
}/**模拟从数据库或缓存中获取权限数据
* @param userName
* @return
*/
private Set<String> getPermissionsByUserName(String userName) {
Set<String> permissions = new HashSet<String>();
permissions.add("user:delete");
permissions.add("user:add");
return permissions;
}/**模拟数据查询
* @param userName
* @return
*/
private Set<String> getRolesByUserName(String userName) {
Set<String> roles = new HashSet<String>();
roles.add("admin");
roles.add("user");
return roles;
}/* 用来做认证
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//1.从主体传过来的认证信息中,获取用户名
String userName = (String) token.getPrincipal();
//2.通过用户名找到数据库中获取凭证
String password = getPasswordByUserName(userName);
if (password == null) {
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("fusiping",password,"customRealm");
//识别加盐
authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("fusiping"));
return authenticationInfo;
}/**模拟数据库查询凭证
* @param userName
* @return
*/
private String getPasswordByUserName(String userName) {
return map.get(userName);
}
public static void main(String[] args) {
//加盐:“fusiping”
Md5Hash md5Hash = new Md5Hash("123456","fusiping");
System.out.println(md5Hash.toString());
}
}
测试:
package com.imooc.test;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.junit.Test;import com.imooc.shrio.realm.CustomRealm;
/**测试
* @author fusiping
* 2018年11月23日
*/
public class CustomRealmTest {@Test
public void testCustomRealm() {
//自定义
CustomRealm customRealm = new CustomRealm();
//1.构建securityManage环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
defaultSecurityManager.setRealm(customRealm);
//加密
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("md5");
//加密次数
matcher.setHashIterations(1);
customRealm.setCredentialsMatcher(matcher);
//设置secutityManager环境
SecurityUtils.setSecurityManager(defaultSecurityManager);
//2.主体提交认证请求
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("fusiping","123456");
subject.login(token);
//结果:isAuthenticated:true
System.out.println("isAuthenticated:"+subject.isAuthenticated());
subject.checkRole("admin");
subject.checkPermission("user:delete");
}
}
shiro+spring整合:
package com.fsp.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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
public class CustomRealm extends AuthorizingRealm {
//模拟数据库查询
Map<String, String> map = new HashMap<String, String>(16);
{
map.put("fusiping", "cc2bf701edeca9268997bab3f5b6527d");//123456,Md5加盐“fusiping”,加密后e10adc3949ba59abbe56e057f20f883e
super.setName("customRealm");
}
/* 用来做授权
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userName = (String) principals.getPrimaryPrincipal();
//从数据库或者从缓存中获取角色数据
Set<String> roles = getRolesByUserName(userName);
//通过用户从从数据库或者从缓存中获取权限数据
Set<String> permissions = getPermissionsByUserName(userName);
SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
simpleAuthenticationInfo.setStringPermissions(permissions);
simpleAuthenticationInfo.setRoles(roles);
return simpleAuthenticationInfo;
}
/**模拟从数据库或缓存中获取权限数据
* @param userName
* @return
*/
private Set<String> getPermissionsByUserName(String userName) {
Set<String> permissions = new HashSet<String>();
permissions.add("user:delete");
permissions.add("user:add");
return permissions;
}
/**模拟数据查询
* @param userName
* @return
*/
private Set<String> getRolesByUserName(String userName) {
Set<String> roles = new HashSet<String>();
roles.add("admin");
roles.add("user");
return roles;
}
/* 用来做认证
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//1.从主体传过来的认证信息中,获取用户名
String userName = (String) token.getPrincipal();
//2.通过用户名找到数据库中获取凭证
String password = getPasswordByUserName(userName);
if (password == null) {
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo("fusiping",password,"customRealm");
//识别加盐
authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("fusiping"));
return authenticationInfo;
}
/**模拟数据库查询凭证
* @param userName
* @return
*/
private String getPasswordByUserName(String userName) {
return map.get(userName);
}
}
controller:
package com.fsp.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.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fsp.controller.req.UserModel;
@Controller
public class UserController {
@RequestMapping(value="/subLogin",method = RequestMethod.POST,produces = "application/json;charset=utf-8")
@ResponseBody
public String subLogin(UserModel userModel) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(userModel.getUsername(),userModel.getPassword());
try {
subject.login(token);
} catch (AuthenticationException e) {
return "登陆异常:"+e.getMessage();
}
return "登陆成功";
}
}
userModel:
package com.fsp.controller.req;
import lombok.Getter;
import lombok.Setter;
/**登陆接收model
* @author fusiping
* 2018年11月23日
*/
@Getter
@Setter
public class UserModel {
private String username;
private String password;
}
配置文件:
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_3_0.xsd"
version="3.0"><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><!-- 配置spring容器的路径 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/spring.xml</param-value>
</context-param>
<!-- 对spring开始监听 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>springServlet</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>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" 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"
default-lazy-init="true"><description>Shiro Configuration</description>
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="login.html" />
<property name="unauthorizedUrl" value="403.html"/>
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions"/>
</property>
</bean>
<!-- Shiro权限过滤过滤器定义 -->
<bean name="shiroFilterChainDefinitions" class="java.lang.String">
<constructor-arg>
<value>
/login.html = anon
/subLogin = anon
/subLogin2 = anon
/* = authc
</value>
</constructor-arg>
</bean>
<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="realm" />
</bean>
<bean class="com.fsp.shiro.realm.CustomRealm" id="realm">
<property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean>
<!-- 加密对象-->
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher" id="credentialsMatcher">
<property name="hashAlgorithmName" value="md5"/>
<property name="hashIterations" value="1"/>
</bean></beans>
springmvc.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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"
default-lazy-init="true">
<context:component-scan base-package="com.fsp.controller"/>
<mvc:annotation-driven/>
<mvc:resources mapping="/*" location="/"/>
</beans>
login.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="subLogin" method="post">
用户名:<input type="text" name="username"/><br>
密码:<input type="password" name="password"/><br>
<input type="submit" value="登陆">
</form></body>
</html>
shiro集成spring从数据库获取数据
spring-dao.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="url" value="jdbc:mysql://localhost:3333/test1"/>
<property name="username" value="test1"/>
<property name="password" value="fsp648734!"/>
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" 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"
default-lazy-init="true"><import resource="spring-dao.xml"/>
<context:component-scan base-package="com.fsp"/>
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="login.html" />
<property name="unauthorizedUrl" value="403.html"/>
<!--
<property name="filters">
<map>
<entry key="cas" value-ref="casFilter"/>
<entry key="authc" value-ref="formAuthenticationFilter"/>
</map>
</property> -->
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions"/>
</property>
</bean>
<!-- Shiro权限过滤过滤器定义 -->
<bean name="shiroFilterChainDefinitions" class="java.lang.String">
<constructor-arg>
<value>
/login.html = anon
/subLogin = anon
/* = authc
</value>
</constructor-arg>
</bean>
<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="realm" />
</bean>
<bean class="com.fsp.shiro.realm.CustomRealm" id="realm">
<property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean>
<!-- 加密对象-->
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher" id="credentialsMatcher">
<property name="hashAlgorithmName" value="MD5"/>
<property name="hashIterations" value="1"/>
</bean></beans>
CustomRealm:
package com.fsp.shiro.realm;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import com.fsp.dao.UserDao;
import com.fsp.entity.User;@Component
public class CustomRealm extends AuthorizingRealm {@Autowired
private UserDao userDao;/* 用来做授权
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userName = (String) principals.getPrimaryPrincipal();
//从数据库或者从缓存中获取角色数据
Set<String> roles = getRolesByUserName(userName);
//通过用户从从数据库或者从缓存中获取权限数据
Set<String> permissions = new LinkedHashSet<String>();
for (String role : roles) {
Set<String> list = getPermissionsByUserName(role);
permissions.addAll(list);
}
SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
simpleAuthenticationInfo.setStringPermissions(permissions);
simpleAuthenticationInfo.setRoles(roles);
return simpleAuthenticationInfo;
}/**模拟从数据库或缓存中获取权限数据
* @param userName
* @return
*/
private Set<String> getPermissionsByUserName(String roleName) {
List<String> list = userDao.queryPermissionsByUserName(roleName);
Set<String> permissions = new HashSet<String>(list);
return permissions;
}/**数据查询角色
* @param userName
* @return
*/
private Set<String> getRolesByUserName(String userName) {
List<String> list = userDao.queryRolesByUserName(userName);
Set<String> roles = new HashSet<String>(list);
return roles;
}/* 用来做认证
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//1.从主体传过来的认证信息中,获取用户名
String userName = (String) token.getPrincipal();
//2.通过用户名找到数据库中获取凭证
String password = getPasswordByUserName(userName);
if (password == null) {
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName,password,"customRealm");
//识别加盐,盐值随意
authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(userName));
return authenticationInfo;
}/*public static void main(String[] args) {
//数据源+盐
Md5Hash md5 = new Md5Hash("123456","fusiping");
System.out.println(md5.toString());
}*/
/**模拟数据库查询凭证
* @param userName
* @return
*/
private String getPasswordByUserName(String userName) {
User user = userDao.getUserByUserName(userName);
if (user != null) {
return user.getPassword();
}
return null;
}
}
dao:
package com.fsp.dao;
import java.util.List;
import com.fsp.entity.User;
public interface UserDao {
User getUserByUserName(String userName);
List<String> queryRolesByUserName(String userName);
List<String> queryPermissionsByUserName(String roleName);
}
daoImpl:
package com.fsp.dao.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;import com.fsp.dao.UserDao;
import com.fsp.entity.User;@Component
public class UserDaoImpl implements UserDao{@Autowired
private JdbcTemplate jdbcTemplate;
/* 数据库查询密码
* @param userName
* @return
*/
public User getUserByUserName(String userName) {
String sql = "select username, password from users where username = ?";
List<User> list = jdbcTemplate.query(sql, new String[] {userName}, new RowMapper<User>() {
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
return user;
}
});
if (CollectionUtils.isEmpty(list)) {
return null;
}
return list.get(0);
}/* 数据库查询角色
* @param userName
* @return
*/
public List<String> queryRolesByUserName(String userName) {
String sql = "select role_name from user_roles where username = ?";
return jdbcTemplate.query(sql, new String[] {userName}, new RowMapper<String>() {
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString("role_name");
}
});
}/* 根据角色返回权限数据
* @param roleName
* @return
*/
public List<String> queryPermissionsByUserName(String roleName) {
String sql = "select permission from roles_permissions where role_name = ?";
return jdbcTemplate.query(sql, new String[] {roleName}, new RowMapper<String>() {
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString("permission");
}
});
}}
controller:
package com.fsp.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.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;import com.fsp.controller.req.UserModel;
@Controller
public class UserController {@RequestMapping(value="/subLogin",method = RequestMethod.POST,produces = "application/json;charset=utf-8")
@ResponseBody
public String subLogin(UserModel userModel) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(userModel.getUsername(),userModel.getPassword());
try {
subject.login(token);
} catch (AuthenticationException e) {
return "登陆异常:"+e.getMessage();
}
if (subject.hasRole("admin")) {
subject.checkPermission("user:delete");
return "有admin权限";
}
return "无admin权限";
}
}
通过注解配置权限:
pom.xml添加:
<!-- 开启注解方式授权shiro -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
springmvc.xml添加:
<!-- 开启注解方式shrio需要的配置 -->
<aop:config proxy-target-class="true"/>
<bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
controller添加:
/**当前主题必须具备amdin觉得才可以访问
* @return
*/
@RequiresRoles("admin")
@RequestMapping(value="/testRole",method=RequestMethod.GET)
@ResponseBody
public String testRole() {
return "testRole success";
}
/**推荐使用的方法
* @return
*/
@RequiresPermissions("user:delete")
@RequestMapping(value="/testRole1",method=RequestMethod.GET)
@ResponseBody
public String testRole1() {
return "testRole success";
}
shrio内置过滤器:
认证过滤器:anon,authBasic,authc,user,logout
anon:不需要任何认证,直接访问
authBasic:HTTP基本认证
authc:需要认证之后才可以访问
user:需要当前存在用户才能访问
logout;退出、
授权过滤器:perms,roles,ssl,port
perms:需要具备相关权限才可以访问
roles:跟perms差不多,在[]里面满足的相关权限
ssl:https协议
port:[]里面的端口
自定义filter:
package com.fsp.filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;/**自动一授权,如果包含其中一个权限,则执行
* @author fusiping
* 2018年11月27日
*/
public class RoleOrFilter 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 true;
}
for (String role : roles) {
if (subject.hasRole(role)) {
return true;
}
}
return false;
}
}
spring.xml:
注入自定义bean
<!-- 自定义file -->
<bean class="com.fsp.filter.RoleOrFilter" id="roleOrFilter"></bean>
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="login.html" />
<property name="unauthorizedUrl" value="403.html"/>
<!-- 自定义授权过滤器-->
<property name="filters">
<map>
<entry key="rolesOr" value-ref="roleOrFilter"/>
</map>
</property>
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions"/>
</property>
</bean>
<!-- Shiro权限过滤过滤器定义 -->
<bean name="shiroFilterChainDefinitions" class="java.lang.String">
<constructor-arg>
<value>
/login.html = anon
/subLogin = anon
/testRole = roles["admin","admin1"] //roles必须包含里面两个角色才能执行
/testRole1 = rolesOr["admin","admin1"] //rolesOr包含其中一个角色就可以执行
/* = authc
</value>
</constructor-arg>
</bean>
controller:
/**roles["admin","admin1"] //roles必须包含里面两个角色才能执行
* @return
*/
@RequestMapping(value="/testRole",method=RequestMethod.GET)
@ResponseBody
public String testRole() {
return "testRole success";
}
/**rolesOr["admin","admin1"] //rolesOr包含其中一个角色就可以执行
* @return
*/
@RequestMapping(value="/testRole1",method=RequestMethod.GET)
@ResponseBody
public String testRole1() {
return "testRole success";
}
shiro会话管理
shiro session管理
sessionmanager,sessionDAO
Redis实现session共享
redis实现Session共享存在的问题
引入maven依赖:
<!-- 通过redis实现Session共享 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
spring.xml配置文件添加:
<!-- 创建sessionManager对象 -->
<bean class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager" id="sessionManager">
<property name="sessionDAO" ref="redisSessionDao"/>
</bean>
<bean class="com.fsp.session.RedisSessionDao" id="redisSessionDao"/>
<!--修改-->
<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="realm" />
<property name="sessionManager" ref="sessionManager"/>
</bean>
RedisSessionDao:
package com.fsp.session;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;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.beans.factory.annotation.Autowired;
import org.springframework.util.SerializationUtils;import com.fsp.util.JedisUtil;
/**
* @author fusiping
* 2018年11月27日
*/
public class RedisSessionDao extends AbstractSessionDAO{
@Autowired
private JedisUtil jedisUtil;
//前缀
private final String SHIRO_SESSION_PREFIX = "fsp-session";
//前缀+key组成的key
private byte[] getKey(String key) {
return (SHIRO_SESSION_PREFIX + key).getBytes();
}
/**保存session
* @param session
*/
private void savaSession(Session session) {
if (session != null && session.getId() != null) {
byte[] key = getKey(session.getId().toString());
byte[] value = SerializationUtils.serialize(session);
jedisUtil.set(key,value);
jedisUtil.expire(key,600);
}
}
/* 创建sessionID
* @param session
* @return
*/
@Override
protected Serializable doCreate(Session session) {
Serializable sessionId = generateSessionId(session);
//捆绑session,sessionId
assignSessionId(session, sessionId);
savaSession(session);
return sessionId;
}
@Override
protected Session doReadSession(Serializable sessionId) {
System.out.println("read session");
if (sessionId == null) {
return null;
}
byte[] key = getKey(sessionId.toString());
byte[] value = jedisUtil.get(key);
//反序列化成json对象
return (Session) SerializationUtils.deserialize(value);
}/* 更新session
* @param session
* @throws UnknownSessionException
*/
public void update(Session session) throws UnknownSessionException {
savaSession(session);
}/* 删除session
* @param session
*/
public void delete(Session session) {
if (session == null || session.getId() == null) {
return ;
}
byte[] key = getKey(session.getId().toString());
jedisUtil.del(key);
}/* 获取正在活动的session
* @return
*/
public Collection<Session> getActiveSessions() {
Set<byte[]> keys = jedisUtil.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(jedisUtil.get(key));
sessions.add(session);
}
return sessions;
}
}
添加spring-redis.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean class="redis.clients.jedis.JedisPool" id="jedisPool">
<constructor-arg ref="jedisPoolConfig"/>
<constructor-arg value="127.0.0.1"/>
<constructor-arg value="6379"/>
</bean>
<bean class="redis.clients.jedis.JedisPoolConfig" id="jedisPoolConfig"/>
</beans>
spring.xml引入spring-resdis.xml:
<import resource="spring-redis.xml"/>
JedisUtil工具类:
package com.fsp.util;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import lombok.val;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;/**redis访问工具包
* @author fusiping
* 2018年11月27日
*/
@Component
public class JedisUtil {@Autowired
private JedisPool jedisPool;
private Jedis getResource() {
return jedisPool.getResource();
}
public byte[] set(byte[] key, byte[] value) {
Jedis jedis = getResource();
try {
jedis.set(key, value);
return value;
} finally {
jedis.close();
}
}public void expire(byte[] key, int i) {
Jedis jedis = getResource();
try {
jedis.expire(key, i);
} finally {
jedis.close();
}
}public byte[] get(byte[] key) {
Jedis jedis = getResource();
try {
return jedis.get(key);
} finally {
jedis.close();
}
}public void del(byte[] key) {
Jedis jedis = getResource();
try {
jedis.del(key);
} finally {
jedis.close();
}
}public Set<byte[]> keys(String sHIRO_SESSION_PREFIX) {
Jedis jedis = getResource();
try {
//转成二进制
return jedis.keys((sHIRO_SESSION_PREFIX + "*").getBytes());
} finally {
jedis.close();
}
}
}
结果:
注意:必须先启动redis:运行命令:
但是每次请求都会调用多次session,需要优化性能:
所以自定义 SessionManager:
package com.fsp.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;/**自定义sessionmanager
* @author fusiping
* 2018年11月27日
*/
public class CustomSessionManager extends DefaultWebSessionManager {
/* 重新retrieveSession
* 先从request中获取,取不到则从redis,取到后在set到request
* @param sessionKey
* @return
* @throws UnknownSessionException
*/
protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
// 1先获取sessionId
Serializable sessionId = getSessionId(sessionKey);
ServletRequest request = null;
//先反对是不是WebSessionKey类型
if (sessionKey instanceof WebSessionKey) {
//从sessionkey总获取request
request = ((WebSessionKey) sessionKey).getServletRequest();
}
//如果request != null && sessionId != null
if (request != null && sessionId != null) {
//直接从request中获取session
return (Session) request.getAttribute(sessionId.toString());
}
//那么从retrieveSession中获取
Session session = super.retrieveSession(sessionKey);
if (request != null && sessionId != null) {
request.setAttribute(sessionId.toString(), session);
}
return session;
}}
修改spring.xml:
<!-- 修改sessionManager为自定义对象 -->
<bean class="com.fsp.session.CustomSessionManager" id="sessionManager">
<property name="sessionDAO" ref="redisSessionDao"/>
</bean><bean class="com.fsp.session.RedisSessionDao" id="redisSessionDao"/>
优化sessionManager
package com.fsp.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;/**自定义sessionmanager
* @author fusiping
* 2018年11月27日
*/
public class CustomSessionManager extends DefaultWebSessionManager {
/* 重新retrieveSession
* 先从request中获取,取不到则从redis,取到后在set到request
* @param sessionKey
* @return
* @throws UnknownSessionException
*/
@Override
protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
// 1先获取sessionId
Serializable sessionId = getSessionId(sessionKey);
ServletRequest request = null;
//先反对是不是WebSessionKey类型
if (sessionKey instanceof WebSessionKey) {
//从sessionkey总获取request
request = ((WebSessionKey) sessionKey).getServletRequest();
}
//如果request != null && sessionId != null
if (request != null && sessionId != null) {
//直接从request中获取session
Session session = (Session) request.getAttribute(sessionId.toString());
if (session != null ) {
return session;
}
}
//那么从retrieveSession中获取
Session session = super.retrieveSession(sessionKey);
if (request != null && sessionId != null) {
request.setAttribute(sessionId.toString(), session);
}
return session;
}}
优化之后就不用每次都多次调用redis
spring.xml添加:
<!-- 修改定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="realm" />
<property name="sessionManager" ref="sessionManager"/>
<property name="cacheManager" ref="redisCacheManager"/> //shrio session 缓存
</bean>
<!-- shrio session 缓存 -->
<bean id="redisCacheManager" class="com.fsp.cache.RedisCacheManager"/>
RedisCacheManager:
package com.fsp.cache;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;public class RedisCacheManager implements CacheManager{
@Autowired
private RedisCache redisCache;public <K, V> Cache<K, V> getCache(String arg0) throws CacheException {
return redisCache;
}}
RedisCache:
package com.fsp.cache;
import java.util.Collection;
import java.util.Set;import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.SerializationUtils;import com.fsp.util.JedisUtil;
@Component
public class RedisCache<K, V> implements Cache<K, V>{
@Autowired
private JedisUtil jedisUtil;
private final String cache_prefix = "fsp-cache";private byte[] getKey(K k) {
if (k instanceof String) {
return (cache_prefix + k).getBytes();
}
return SerializationUtils.serialize(k);
}
public void clear() throws CacheException {
// TODO Auto-generated method stub
}public V get(K k) throws CacheException {
System.out.println("从reids中获取权限数据");
byte[] value = jedisUtil.get(getKey(k));
if (value != null ) {
return (V) SerializationUtils.deserialize(value);
}
return null;
}public Set<K> keys() {
return null;
}public V put(K arg0, V arg1) throws CacheException {
byte[] key = getKey(arg0);
byte[] value = SerializationUtils.serialize(arg1);
jedisUtil.set(key, value);
jedisUtil.expire(key, 600);
return arg1;
}/* 删除
* @param arg0
* @return
* @throws CacheException
*/
public V remove(K arg0) throws CacheException {
byte[] key = getKey(arg0);
byte[] value = jedisUtil.get(key);
jedisUtil.del(key);
if (value != null) {
return (V) SerializationUtils.deserialize(value);
}
return null;
}public int size() {
// TODO Auto-generated method stub
return 0;
}public Collection<V> values() {
// TODO Auto-generated method stub
return null;
}}
记住我功能:
spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" 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"
default-lazy-init="true"><import resource="spring-dao.xml"/>
<import resource="spring-redis.xml"/>
<context:component-scan base-package="com.fsp"/>
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="login.html" />
<property name="unauthorizedUrl" value="403.html"/>
<!--
<property name="filters">
<map>
<entry key="cas" value-ref="casFilter"/>
<entry key="authc" value-ref="formAuthenticationFilter"/>
</map>
</property> -->
<property name="filters">
<map>
<entry key="rolesOr" value-ref="roleOrFilter"/>
</map>
</property>
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions"/>
</property>
</bean>
<!-- Shiro权限过滤过滤器定义 -->
<bean name="shiroFilterChainDefinitions" class="java.lang.String">
<constructor-arg>
<value>
/login.html = anon
/subLogin = anon
/testRole = roles["admin","admin1"]
/testRole1 = rolesOr["admin","admin1"]
<!-- /testRole = roles["admin"]
/testRole1 = roles["admin","admin1"] 同时具备admin,admin1
/testperms = perms["user:delete"]
/testperms1 = perms["user:delete","user:update"] 同时具备user:delete,user:update -->
/* = authc
</value>
</constructor-arg>
</bean>
<!-- 自定义file -->
<bean class="com.fsp.filter.RoleOrFilter" id="roleOrFilter"></bean>
<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="realm" />
<property name="sessionManager" ref="sessionManager"/>
<property name="cacheManager" ref="redisCacheManager"/>
<property name="rememberMeManager" ref="cookieRememberMeManager"/>
</bean>
<bean class="com.fsp.shiro.realm.CustomRealm" id="realm">
<property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean>
<!-- 加密对象-->
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher" id="credentialsMatcher">
<property name="hashAlgorithmName" value="MD5"/>
<property name="hashIterations" value="1"/>
</bean><!-- 创建sessionManager对象 -->
<bean class="com.fsp.session.CustomSessionManager" id="sessionManager">
<property name="sessionDAO" ref="redisSessionDao"/>
</bean>
<bean class="com.fsp.session.RedisSessionDao" id="redisSessionDao"/>
<!-- shrio session 缓存 -->
<bean id="redisCacheManager" class="com.fsp.cache.RedisCacheManager"/>
<bean class="org.apache.shiro.web.mgt.CookieRememberMeManager" id="cookieRememberMeManager">
<property name="cookie" ref="simpleCookie"/>
</bean>
<bean class="org.apache.shiro.web.servlet.SimpleCookie" id="simpleCookie">
<constructor-arg value="rememberMe"/>
<property name="maxAge" value="20000000"/>
</bean>
</beans>
loginController:
@RequestMapping(value="/subLogin",method = RequestMethod.POST,produces = "application/json;charset=utf-8")
@ResponseBody
public String subLogin(UserModel userModel) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(userModel.getUsername(),userModel.getPassword());
try {
token.setRememberMe(userModel.isRememberMe());
subject.login(token);
} catch (AuthenticationException e) {
return "登陆异常:"+e.getMessage();
}
if (subject.hasRole("admin")) {
subject.checkPermission("user:delete");
return "有admin权限";
}
return "无admin权限";
}
login.xml:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="subLogin" method="post">
用户名:<input type="text" name="username"/><br>
密码:<input type="password" name="password"/><br>
<input type="checkbox" name="rememberMe"/>记住我<br>
<input type="submit" value="登陆">
</form></body>
</html>