一 maven依赖
1.1 普通maven
<properties>
<shiro.version>1.2.4</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-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
1.2 springboot需要的maven
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
二 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
default-lazy-init="true">
<description>ShiroConfig</description>
<!--安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--设置自定义Realm-->
<property name="realm" ref="shiroDbRealm"/>
<!--将缓存管理器,交给安全管理器-->
<property name="cacheManager" ref="shiroEhcacheManager"/>
</bean>
<!-- 項目自定义的Realm -->
<bean id="shiroDbRealm" class="com.msunsoft.shiro.ShiroDbRealm"/>
<!-- Shiro Filter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 安全管理器 -->
<property name="securityManager" ref="securityManager"/>
<!-- 默认的登陆访问url -->
<property name="loginUrl" value="/login"/>
<!-- 登陆成功后跳转的url -->
<property name="successUrl" value="/index"/>
<!-- 没有权限跳转的url -->
<property name="unauthorizedUrl" value="/unauth"/>
<property name="filterChainDefinitions">
<value>
/commons/** = anon <!-- 不需要认证 -->
/static/** = anon
/images/** = anon
/scripts/** = anon
/styles/** = anon
/login = anon
/initLogin = anon
/selectRolePage = anon
/getChildRoleByPid = anon
/logout = anon
/** = anon
<!-- /** = authc --> <!-- 需要认证 -->
</value>
</property>
</bean>
<!-- 用户授权信息Cache, 采用EhCache -->
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:spring/ehcache-shiro.xml"/>
</bean>
<!-- 在方法中 注入 securityManager ,进行代理控制 -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
<property name="arguments" ref="securityManager"/>
</bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- AOP式方法级权限检查 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor"/>
<!-- 启用shrio授权注解拦截方式 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
</beans>
2.1 ehcache-shiro.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE xml>
<ehcache updateCheck="false" name="shiroCache">
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
</ehcache>
三 shiro后台
3.1 ShiroDbRealm.java
package com.msunsoft.shiro;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.msunsoft.model.User;
import com.msunsoft.service.RoleService;
import com.msunsoft.service.UserService;
import com.msunsoft.utils.UserInfoCache;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @description:shiro权限认证
*/
public class ShiroDbRealm extends AuthorizingRealm {
private static Logger LOGGER = LoggerFactory.getLogger(ShiroDbRealm.class);
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
/**
* Shiro登录认证(原理:用户提交 用户名和密码 --- shiro 封装令牌 ---- realm 通过用户名将密码查询返回 ---- shiro 自动去比较查询出密码和用户输入密码是否一致---- 进行登陆控制 )
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
LOGGER.info("Shiro开始登录认证");
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
User user = userService.findUserByLoginName(token.getUsername());
// 账号不存在
if (user == null) {
return null;
}
// 账号未启用
if (user.getStatus() == 1) {
return null;
}
// List<Long> roleList = roleService.findRoleIdListByUserId(user.getId());
List<Long> roleList = new ArrayList<Long>();
roleList.add(Long.parseLong(UserInfoCache.getLoginnamerolecache().get(token.getUsername())));
ShiroUser shiroUser = new ShiroUser(user.getId(), user.getLoginname(), user.getName(), roleList);
// 认证缓存信息
return new SimpleAuthenticationInfo(shiroUser, user.getPassword().toCharArray(), getName());
}
/**
* Shiro权限认证
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
List<Long> roleList = shiroUser.roleList;
Set<String> urlSet = Sets.newHashSet();
for (Long roleId : roleList) {
List<Map<Long, String>> roleResourceList = roleService.findRoleResourceListByRoleId(roleId);
if (roleResourceList != null) {
for (Map<Long, String> map : roleResourceList) {
if (StringUtils.isNoneBlank(map.get("URL"))) {
urlSet.add(map.get("URL"));
}
}
}
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(urlSet);
return info;
}
}
3.2 登录controller
/**
* 首页
*
* @param model
* @return
*/
@RequestMapping(value = "/index")
public String index(Model model) {
return "/index";
// return "/index";
}
/**
* POST 登录 shiro 写法
*
* @param username 用户名
* @param password 密码
* @param request
* @param model
* @return
*/
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public Result loginPost(String userName,String roleId, HttpServletRequest request, Model model) {
LOGGER.info("POST请求登录");
Result result = new Result();
if (StringUtils.isBlank(userName)) {
result.setMsg("用户名不能为空");
return result;
}
String password = UserInfoCache.getLoginnamepwdcache().get(userName).getPassword();
if (StringUtils.isBlank(password)) {
result.setMsg("密码不能为空");
return result;
}
UserInfoCache.getLoginnamerolecache().put(userName, roleId);
Subject user = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(userName, DigestUtils.md5Hex(password).toCharArray());
token.setRememberMe(true);
try {
user.login(token);
} catch (UnknownAccountException e) {
LOGGER.error("账号不存在:{}", e);
result.setMsg("账号不存在");
return result;
} catch (DisabledAccountException e) {
LOGGER.error("账号未启用:{}", e);
result.setMsg("账号未启用");
return result;
} catch (IncorrectCredentialsException e) {
LOGGER.error("密码错误:{}", e);
result.setMsg("密码错误");
return result;
} catch (RuntimeException e) {
LOGGER.error("未知错误,请联系管理员:{}", e);
result.setMsg("未知错误,请联系管理员");
return result;
}
result.setSuccess(true);
return result;
}
四 jsp
// 登录
function submitForm() {
//$('#loginform').submit();
$.ajax({
type : "post",
url : path + '/zymiLoginPost',// 全路径
data : {
userCode : $("#userCode").val(),
password : $("#password").val()
},
dataType : "json",// 指定参数类型
success : function(result) {// 接收返回结果,类型为一个对象
if (result.success) {
// window.location.href = path + '/selectPage?userCode='
// + $("#userCode").val();
window.location.href = path + '/docMainPage?userCode='
+ $("#userCode").val();
} else {
alert(result.msg);
}
}
});
}