pom.xml
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext-mvc.xml,classpath*:applicationContext.xml,classpath*:applicationContext-shiro.xml</param-value>
</context-param>
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<!-- 該值缺省爲false,表示生命週期由SpringApplicationContext管理,設置爲true則表示由ServletContainer管理 -->
<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>
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="shiroCache">
<diskStore path="java.io.tmpdir" />
<defaultCache
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"/>
</ehcache>
applicationContext-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 設置自定義realm -->
<property name="realm" ref="shiroDbRealm"/>
<!-- 將緩存管理器交給安全管理器 -->
<property name="cacheManager" ref="cacheManager"/>
</bean>
<!-- Realm實現 -->
<bean id="shiroDbRealm" class="com.per.util.ShiroDbRealm" >
<property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean>
<!-- 緩存管理器 使用Ehcache實現 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml" />
</bean>
<!-- 數據庫保存的密碼是使用MD5算法加密的,所以這裏需要配置一個密碼匹配對象 -->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"/>
</bean>
<!-- Shiro的Web過濾器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,這個屬性是必須的 -->
<property name="securityManager" ref="securityManager" />
<!-- 要求登錄時的鏈接(可根據項目的URL進行替換),非必須的屬性,默認會自動尋找Web工程根目錄下的"/login.jsp"頁面 -->
<property name="loginUrl" value="/user/login.do" />
<!-- 登錄成功後要跳轉的連接 -->
<!-- <property name="successUrl" value="/system/main"/> -->
<!-- 用戶訪問未對其授權的資源時,所顯示的連接 -->
<property name="unauthorizedUrl" value="/user/login.do" />
<!-- Shiro連接約束配置,即過濾鏈的定義 -->
<!-- anon表示此地址不需要任何權限即可訪問 -->
<!-- perms[user:query]表示訪問此連接需要權限爲user:query的用戶 -->
<!-- roles[manager]表示訪問此連接需要用戶的角色爲manager -->
<!-- authc 要權限纔可訪問 -->
<property name="filterChainDefinitions">
<value>
/user/login.do = anon
/cust/list.do = authc
/cust/chancelist.do = roles[manager]
</value>
</property>
</bean>
<!-- 保證實現了Shiro內部lifecycle函數的bean執行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans>
ShiroDbRealm.java
import com.htjx.crm.model.Empl;
import com.htjx.crm.model.Role;
import com.htjx.crm.model.SysPermission;
import com.htjx.crm.service.EmplService;
import com.htjx.crm.service.RoleService;
import org.apache.shiro.authc.*;
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 javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Created by yangbin on 2017/5/13.
*/
public class ShiroDbRealm extends AuthorizingRealm {
@Resource
private EmplService emplService;
@Resource
private RoleService roleService;
/**
* 提供用戶信息返回權限信息
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
Empl user = (Empl)principalCollection.getPrimaryPrincipal();
Role role = emplService.getRoleByEmplId(user.getId());
Set<String> sysPermissionSet = new HashSet<>();
List<SysPermission> permissionList = roleService.getPermissionListByRoleId(role.getId());
permissionList.forEach(permission -> {
sysPermissionSet.add(permission.getUrl());
});
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(sysPermissionSet);
return simpleAuthorizationInfo;
}
/**
* 提供賬戶信息返回認證信息
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
Empl user = emplService.checkUserName(token.getUsername());
if (user == null) {
// 用戶名不存在拋出異常
throw new UnknownAccountException();
}
if (0 == user.getStatus()) {
// 用戶被管理員鎖定拋出異常
throw new LockedAccountException();
}
// 數據庫數據庫中的密碼只做了一次md5,因此不傳salt
return new SimpleAuthenticationInfo(user, user.getUserPwd(), user.getUserName());
}
}
LoginController.java
import com.per.crm.constants.UserConstants;
import com.per.crm.service.EmplService;
import com.per.crm.util.BaseController;
import com.per.crm.util.MD5Utils;
import com.per.crm.vo.EmplVo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.annotation.Resource;
@Controller
@RequestMapping("/user")
public class LoginController extends BaseController {
private Logger logger = LoggerFactory.getLogger(LoginController.class);
@Resource
private EmplService emplService;
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(String userName, String pwd) {
EmplVo empl = emplService.emplLogin(userName, MD5Utils.toMD5(pwd));
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, pwd);
usernamePasswordToken.setRememberMe(true);
subject.login(usernamePasswordToken);
// 將用戶信息放入session
session.setAttribute(UserConstants.SESSION_KEY_USER_ID, empl);
return "redirect:/cust/list.do";
}
}