针对旧系统改造,由于spring版本原因,使用的是Security3做权限控制,通过xml方式进行配置。
总体分为:
1、自定义权限初始化
获取系统所有权限,重新进行组装,自定义HibernateFilterInvocationSecurityMetadataSourceFactoryBean类组装权限:
public class HibernateFilterInvocationSecurityMetadataSourceFactoryBean
implements FilterInvocationSecurityMetadataSource {
// 用于查询权限信息的hql语句
@Autowired
private AuthorityService authorityService;
private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
public HibernateFilterInvocationSecurityMetadataSourceFactoryBean() {
}
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
// TODO Auto-generated method stub
if(resourceMap!=null) {
loadResourceDefine();
}
// String url = ((FilterInvocation) object).getRequestUrl();
String url = ((FilterInvocation) object).getRequest().getRequestURI();
Iterator<String> ite = resourceMap.keySet().iterator();
while (ite.hasNext()) {
String resURL = ite.next();
if (url.equalsIgnoreCase(resURL)) {
return resourceMap.get(resURL);
}
}
return null;
}
private void loadResourceDefine() {
resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
List<Authority> resourceList = getAuthorityService().getAll();
for (Authority authority : resourceList) {
if (StringUtils.isNotBlank(authority.getPath())) {
String url = authority.getPath();
if (StringUtils.isNotBlank(url)) {
String role = "PERM_" + authority.getAuthorityId();
ConfigAttribute ca = new SecurityConfig(role);
Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
atts.add(ca);
resourceMap.put(url, atts);
}
}
}
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean supports(Class<?> clazz) {
// TODO Auto-generated method stub
return true;
}
2、用户登录授权
在用户登录完成以后,对该用户拥有的权限进展组装,组装的规则与第一步一样,都是用PERM_加菜单ID来处理。直接让系统用户继承UserDetails,直接覆盖getAuthorities方法
// 覆盖spring security的方法
@Override
@Transient
@JsonIgnore
public Collection<GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>();
for (Authority authority : userAuthorities) {
grantedAuthorities.add(new GrantedAuthorityImpl("PERM_" + authority.getAuthorityId()));
}
return grantedAuthorities;
}
3、自定义的决策器
自定义决策器,原理类似于拦截下当前请求的URL,判断是否在权限集合内,如果在集合内则进行权限判断。先获取本次url所需要的权限,迭代对比当前登录用户的权限,如果符合要求直接return,不符合抛出AccessDeniedException异常
public class DefaultAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object paramObject,
Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException {
// TODO Auto-generated method stub
//如果访问资源不需要任何权限则直接通过
if( configAttributes == null ) {
return ;
}
Iterator<ConfigAttribute> ite = configAttributes.iterator();
//遍历configAttributes看用户是否有访问资源的权限
while( ite.hasNext()){
ConfigAttribute ca = ite.next();
String needRole = ((SecurityConfig)ca).getAttribute();
//ga 为用户所被赋予的权限。 needRole 为访问相应的资源应该具有的权限。
for( GrantedAuthority ga: authentication.getAuthorities()){
if (StringUtils.equals(ga.getAuthority(), needRole)) {
return;
}
}
}
throw new AccessDeniedException("沒有操作权限");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
4、自定义权限拦截器
定义一个MyFilterSecurityInterceptor权限拦截器,继承AbstractSecurityInterceptor,在xml中加入如下配置:

5、添加FILTER
在Security配置中加入custom-filter配置,指向我们自定义的拦截器

6、自定义权限不足处理器
自定义权限不足处理区MyAccessDeniedHandler,继承AccessDeniedHandler重写handler方法,根据自身需求返回相关的提示内容
@Service
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException,
ServletException {
if (isAjaxRequest(request)) {// AJAX请求,使用response发送403
response.sendError(403);
} else if (!response.isCommitted()) {// 非AJAX请求,跳转系统默认的403错误界面,在web.xml中配置
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-type", "text/html;charset=UTF-8");
PrintWriter writer=response.getWriter();
writer.write("<script>alert('您没有权限进行该操作!');</script>");
writer.flush();
return;
// response.sendError(HttpServletResponse.SC_FORBIDDEN,
// accessDeniedException.getMessage());
}
}
public static boolean isAjaxRequest(HttpServletRequest request) {
String requestType = request.getHeader("X-Requested-With");
return requestType != null && requestType.equals("XMLHttpRequest");
}
}