最近做的一个功能使用shiro对接口进行权限限制。也就是说,当前端请求到后台时,首先判断用户是否具有请求该接口的权限,如果有权限,才能进行访问后台API。
1、自定义权限过滤器
package com.cat.arain.web.shiro;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 权限过滤器
*
* @author Arain.liu
*/
public class UrlPermissionsFilter extends PermissionsAuthorizationFilter {
@Override
public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws IOException {
return super.isAccessAllowed(request, response, buildPermissionsFromRequest(request));
}
protected String[] buildPermissionsFromRequest(ServletRequest request) {
HttpServletRequest servletRequest = (HttpServletRequest) request;
String uri = servletRequest.getRequestURI();
String tmpUri = uri.substring(1, uri.length());
String reUri = tmpUri.substring(tmpUri.indexOf("/"), tmpUri.length());
return new String[] { reUri };//返回请求URI
}
}
2、自定义权限解析器
package com.cat.arain.web.shiro.permissions;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.permission.PermissionResolver;
/**
* 自定义权限解析器
* @author arain.liu
* 2018年1月08日 下午1:57:39
*/
public class CustomerPermissionResolver implements PermissionResolver {
@Override
public Permission resolvePermission(String permissionString) {
return new AntPathPermission(permissionString);
}
protected class AntPathPermission implements Permission {
private String permissionString;
public AntPathPermission(String permissionString) {
this.permissionString = permissionString;
}
public String getPermissionString() {
return permissionString;
}
@Override
public boolean implies(Permission p) {
if (!(p instanceof AntPathPermission)) {
return false;
}
AntPathPermission wp = (AntPathPermission) p;
String wpPerm = wp.getPermissionString();
if (StringUtils.equals(wpPerm, permissionString)) {
return true;
}
return false;
}
}
}
然后将这两个类添加到配置中:
<bean id="urlPermissionsFilter" class="com.cat.arain.web.shiro.UrlPermissionsFilter"/>
<bean id="customerPermissionResolver" class="com.cat.arain.web.shiro.permissions.CustomerPermissionResolver"></bean>
3、将自定义的权限解析器添加到自定义的Realm中
<bean id="mayCasRealm" class="com.cat.arain.web.shiro.realm.MyCasRealm">
<property name="permissionResolver" ref="customerPermissionResolver"/>
</bean>
在自定义的Realm中添加权限验证:
/**
* 权限验证
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String accountNo = (String) principals.getPrimaryPrincipal();
if (org.apache.commons.lang3.StringUtils.isBlank(accountNo)) {
return null;
}
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
List<String> permissions = resourceService.getUserMenus(accountNo);
authorizationInfo.addStringPermissions(permissions);
return authorizationInfo;
}
4、配置不同接口的拦截链
<bean id="filterChainManager" class="com.cat.arain.web.shiro.CustomDefaultFilterChainManager">
<property name="loginUrl" value="${shiro.loginUrl}" /> <!--需要登录的请求在未登录的情况下会被拦截到这个地址 -->
<property name="customFilters">
<util:map>
<entry key="authc" value-ref="formAuthenticationFilter" />
<entry key="logout" value-ref="logoutFilter" />
<entry key="cas" value-ref="casFilter" />
<entry key="urlPermissionsFilter" value-ref="urlPermissionsFilter"/>
</util:map>
</property>
<property name="defaultFilterChainDefinitions">
<value>
/login-cas = cas
/assets/** = anon
/*.ico = anon
/nirvana/** =anon
/uploader/** =anon
/logout = logout
/** = authc,urlPermissionsFilter
</value>
</property>
</bean>