前言:上一篇文章讲述了如何使用shiro进行登录认证,其实主要的实现还是自定义Realm,继承AuthorizingRealm实现其中的
doGetAuthenticationInfo方法。上一篇文章链接:https://blog.csdn.net/xcc_2269861428/article/details/95107167
这篇文章主要实现url权限的认证,也就是roles的验证
如图:角色部分===》定义了2个角色,用户管理用户菜单、角色管理角色菜单
用户管理部分==》定义了2个用户
为xcc这个用户分配了2个角色
url权限定义:
此时访问:http://127.0.0.1:8080/SpringShiroDemo/shiro_test/role/getRole/1?_=1562991213180
此时这个url没有被拦。
当我将【xcc】这个用的角色管理去掉
此时在访问:http://127.0.0.1:8080/SpringShiroDemo/shiro_test/role/getRole/1?_=1562991213180
显示权限不足。就是这么简单的功能,简单吧。
用户、角色的增删改查在这里就不描述了。主要说下shiro的关键点及代码展示。
一、ShiroFilterFactoryBean
首先从ShiroFilterFactoryBean说起:这个主要是用来配置登录、错误、url拦截的部分。
这里我重写了ShiroFilterFactoryBean,public class MyShiroFilterFactoryBean extends ShiroFilterFactoryBean {}
因为我们要从数据库中读取出我们配置的权限。只有这样才能称得上是动态修改权限!!!
package com.waysoft.common.shiro;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.shiro.config.Ini;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import com.waysoft.modules.business.integrate.role.dao.RoleDao;
public class MyShiroFilterFactoryBean extends ShiroFilterFactoryBean {
private static final String roles = "authc,roles[{0}]";
@Autowired
private RoleDao roleDao;
@Override
public void setFilterChainDefinitions(String definitions) {
//System.out.println("权限认证");
// /shiro_test/role/** =authc,roles[1]
// /shiro_test/role/**=authc,roles[1]
Ini ini = new Ini();
ini.load(definitions);
Ini.Section section = ini.getSection("urls");
if (CollectionUtils.isEmpty(section)) {
section = ini.getSection("");
}
Map<String,String> data = new HashMap<String,String>();
// 从数据读取出数据
List<Map<String,String>> menuRole = roleDao.getMenuRole();
for(Map<String,String> map : menuRole){
if(data.containsKey(map.get("url"))){
String str = data.get(map.get("url"))+","+map.get("role_id");
data.put(map.get("url"), str);
}else{
data.put(map.get("url"), map.get("role_id"));
}
}
for(String url : data.keySet()){
String str = MessageFormat.format(roles,data.get(url));
section.put(url, str);
}
section.put("/**", "authc");
super.setFilterChainDefinitionMap(section);
}
public void update(){
synchronized (this) {
try {
AbstractShiroFilter shiroFilter = (AbstractShiroFilter)this.getObject();
PathMatchingFilterChainResolver resolver = (PathMatchingFilterChainResolver)shiroFilter.getFilterChainResolver();
DefaultFilterChainManager manager = (DefaultFilterChainManager)resolver.getFilterChainManager();
manager.getFilterChains().clear();
this.getFilterChainDefinitionMap().clear();
Map<String, String> chains = this.getFilterChainDefinitionMap();
Map<String,String> data = new HashMap<String,String>();
// 从数据读取出数据
List<Map<String,String>> menuRole = roleDao.getMenuRole();
for(Map<String,String> map : menuRole){
if(data.containsKey(map.get("url"))){
String str = data.get(map.get("url"))+","+map.get("role_id");
data.put(map.get("url"), str);
}else{
data.put(map.get("url"), map.get("role_id"));
}
}
for(String url : data.keySet()){
String str = MessageFormat.format(roles,data.get(url));
chains.put(url, str);
}
chains.put("/**", "authc");
if (!(CollectionUtils.isEmpty(chains))) {
for (Map.Entry entry : chains.entrySet()) {
String url = (String) entry.getKey();
String chainDefinition = (String) entry.getValue();
manager.createChain(url, chainDefinition);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
System.out.println(MessageFormat.format(roles,2));
}
}
此处重写了filterChainDefinitions方法、定义我们想要的数据。最后生成的样式就是 /shiro_test/role/** =authc,roles[1]
跟我们在ini 中配置的一样
之后自己写了一个update方法,它主要是用来更新权限的,shiro没有那么智能,所以只能我们自己手动去让它更新。
二、AuthorizationFilter
因为shiro默认是验证全部的权限,这里我并不想,有一个就通过,重写了AuthorizationFilter
package com.waysoft.common.shiro;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
public class MyShiroFilter extends AuthorizationFilter {
@Override
protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
Subject subject = getSubject(servletRequest, servletResponse);
String[] roles = (String[]) o;
if (roles == null || roles.length == 0) {
return true;
}
for (String role : roles) {
if (subject.hasRole(role)) {
return true;
}
}
return false;
}
}
三、AuthorizingRealm
这个模块是最主要的了,登录会走doGetAuthenticationInfo方法,授权验证会走doGetAuthorizationInfo
package com.waysoft.common.shiro;
import java.util.Arrays;
import java.util.List;
import org.apache.shiro.SecurityUtils;
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.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import com.waysoft.global.model.User;
import com.waysoft.modules.business.integrate.user.service.UserService;
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 授权验证
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
System.out.println("=============");
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
User user = (User)session.getAttribute("user");
String[] ids = userService.getRoleIdByUserId(user.getId()+"");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
if(ids.length > 0){
List<String> asList = Arrays.asList(ids);
info.addRoles(asList);
return info;
}
return null;
}
/**
* 登录验证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 账户名
String username = (String) authenticationToken.getPrincipal();
User user = userService.findUser(username);
if(user != null){
return new SimpleAuthenticationInfo(username,user.getPassword(),null,getName());
}else{
return null;
}
}
}
最最主要的是我们要在xml配置
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor">
</bean>
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
</bean>
否则有可能不走权限认证。。。
还有就是我们在为用户分配角色后,一定要手动更新权限
项目下载地址:https://download.csdn.net/download/xcc_2269861428/11343864