一、在pom.xml需要引入的jar包
<!-- Apache shiro -->
<properties>
<shiro.version>1.2.3</shiro.version>
</properties>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-cas</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
二、web.xml配置
<!-- The filter-name matches name of a 'shiroFilter' bean inside applicationContext.xml -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
三、新增spring-shiro.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: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-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroDbRealm" />
</bean>
<!-- 項目自定义的Realm -->
<bean id="shiroDbRealm" class="org.szcloud.framework.unit.shiro.ShiroDbRealm" ></bean>
<!-- Shiro Filter -->
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="successUrl" value="/systemChoose.do" />
<property name="unauthorizedUrl" value="/login" />
<property name="filterChainDefinitions">
<value>
/= anon
/admin/** = anon
/unit/** = anon
</value>
</property>
</bean>
<!-- 开启Shiro注解的Spring配置方式的beans。在lifecycleBeanPostProcessor之后运行 -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
<bean id="lifecycleBeanPostProcessor"
class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- shiro为集成spring -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.UnauthorizedException">/login</prop>
</props>
</property>
</bean>
</beans>
代码说明:
- shiroFilter 中 loginUrl 为登录页面地址,successUrl 为登录成功页面地址(如果首先访问受保护 URL 登录成功,则跳转到实际访问页面),unauthorizedUrl 认证未通过访问的页面(前面提到的“未经授权页面”)。
- shiroFilter 中 filters 属性,formAuthenticationFilter 配置为基于表单认证的过滤器。
- shiroFilter 中 filterChainDefinitions 属性,anon 表示匿名访问(不需要认证与授权),authc 表示需要认证,perms[SECURITY_ACCOUNT_VIEW] 表示用户需要提供值为“SECURITY_ACCOUNT_VIEW”Permission 信息。由此可见,连接地址配置为 authc 或 perms[XXX] 表示为受保护资源。
- securityManager 中 realm 属性,配置为我们自己实现的 Realm。关于 Realm,参见前面“Shiro Realm”章节。
- shiroDbRealm为我们自己需要实现的 Realm 类,为了减小数据库压力,可添加添加了缓存机制。在id为shiroDbRealm中加入
-
<property name="cacheManager" ref="shiroCacheManager"/>
- shiroCacheManager 是 Shiro 对缓存框架 EhCache 的配置。
四、将spring-shiro.xml集成入spring-servlet.xml
<import resource="spring-shiro.xml"/>
五、自定义ShiroDbRealm
package org.szcloud.framework.unit.shiro;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.authc.UsernamePasswordToken;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.szcloud.framework.unit.core.domain.PunRoleAccess;
import org.szcloud.framework.unit.service.PunGroupService;
import org.szcloud.framework.unit.service.PunMembershipService;
import org.szcloud.framework.unit.service.PunRoleAccessService;
import org.szcloud.framework.unit.service.PunRoleInfoService;
import org.szcloud.framework.unit.service.PunUserBaseInfoService;
import org.szcloud.framework.unit.vo.PunGroupVO;
import org.szcloud.framework.unit.vo.PunMembershipVO;
import org.szcloud.framework.unit.vo.PunRoleInfoVO;
import org.szcloud.framework.unit.vo.PunUserBaseInfoVO;
public class ShiroDbRealm extends AuthorizingRealm {
@Autowired
@Qualifier("punMembershipServiceImpl")
private PunMembershipService memberService;//身份资格
@Autowired
@Qualifier("punGroupServiceImpl")
private PunGroupService groupService;//组
@Autowired
@Qualifier("punUserBaseInfoServiceImpl")
private PunUserBaseInfoService userService;//用户
@Autowired
@Qualifier("punRoleInfoServiceImpl")
private PunRoleInfoService roleService;//角色
//授权方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
if (null == principals) {
throw new AuthenticationException("principals can not be null");
}
// 获取当前登录的用户名
String userName = (String) super.getAvailablePrincipal(principals);
List<String> roles = new ArrayList<String>();
String[] result = userName.split("_");
Map<String, Object> groupParams = new HashMap<String, Object>();
groupParams.put("orgCode", result[0]);
List<PunGroupVO> groups = groupService.queryResult("eqQueryList",
groupParams);
Map<String,Object> userParams = new HashMap<String, Object>();
userParams.put("userIdCardNumber", result[1]);
List<PunUserBaseInfoVO> users = userService.queryResult("eqQueryList",
userParams);
Map<String,Object> roleParams = new HashMap<String, Object>();
List<PunRoleInfoVO> roleVos = roleService.queryResult("queryByMember", roleParams);
for(PunRoleInfoVO vo : roleVos){
roles.add(vo.getRoleName());//角色
System.out.println("roleName:"+vo.getRoleName());
}
// 给当前用户设置角色
info.addRoles(roles);
// 给当前用户设置权限
// info.addStringPermissions(permissions);
return info;
}
//验证方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String nameAndOrgcode = token.getUsername();
String[] result = nameAndOrgcode.split("_");
Map<String, Object> groupParams = new HashMap<String, Object>();
groupParams.put("orgCode", result[0]);
List<PunGroupVO> groups = groupService.queryResult("eqQueryList",groupParams);//组信息
List<PunUserBaseInfoVO> users = userService.selectByIDCard(result[1]);//用户基础信息
Map<String, Object> memParams = new HashMap<String, Object>();
memParams.put("userId", users.get(0).getUserId());
memParams.put("groupId", groups.get(0).getGroupId());
List<PunMembershipVO> members = memberService.queryResult("eqQueryList",memParams);//身份资格
if(null != members && members.size()>0){
return new SimpleAuthenticationInfo(token.getUsername(),users.get(0).getUserPwd(),this.getName());
}else{
return null;
}
}
}
五、登陆方法
@RequestMapping(value="/login",method=RequestMethod.POST)
public ModelAndView login(PunUserBaseInfoVO vo,Model model,HttpSession session){
if (!VerifyCodeGenerator.getInstance().check(vo.getVerifyCode(), session)) {
model.addAttribute("result", "验证码输入错误");
return new ModelAndView("login");
}
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(vo.getOrgCode()
+ "_" + vo.getUserIdCardNumber(), EncryptUtils.encrypt(vo.getUserPwd()));
// token.setRememberMe(true);//记住我功能
try {
subject.login(token);
List<PunSystemVO> vos = prepareSystemInfo(vo);
return new ModelAndView("systemChoose","sysVOs", vos);
}catch(UnknownAccountException uae){
model.addAttribute("result", "用户不存在");
return new ModelAndView("login");
}catch (IncorrectCredentialsException ice) {
model.addAttribute("result", "登录失败,请核实登录信息!");
return new ModelAndView("login");
}catch (AuthenticationException e) {
e.printStackTrace();
token.clear();
model.addAttribute("result", "登录失败");
return new ModelAndView("login");
}catch (Exception e) {
e.printStackTrace();
return new ModelAndView("login");
}
}
六、登出方法
@RequestMapping(value="/logout",method=RequestMethod.GET)
public ModelAndView logout(HttpSession session){
Subject user = SecurityUtils.getSubject();
user.logout();
return new ModelAndView("/login");
}