基于Spring实现用户权限管理

很多系统都会有多重系统角色,并且每个角色的权限都是不一样的,进行权限管理是一件非常复杂的事情,我这里只是对方法进行权限管理,将权限跟API一一对应起来,如果对这和API没有权限,就无法使用该API,当然这种方法级别的权限管理,范围还是太大,有待进一步细化。

具体的原理就是:使用权限码,假设我的使用的是128位的权限码,那都能设置128种方法的权限,如果需要更多,可以继续加。每一个API方法都对应唯一一个权限码,即当前位是1其余位都是0;每一个用户拥有一个128为的权限集,如果当前位对应1的话,就说明该用户可以操作这个API,否则就是无权限。

用户权限集

每个用户都拥有一个128位权限集,用两个long类型实现。

User.java

@JsonIgnoreProperties(value = {"permissionCodeHigh", "permissionCodeLow"})
public class User implements java.io.Serializable {

private static final long serialVersionUID = -5559386013177436565L;

private String id;                
private String name;            
private String email;        
private String address;        
private String permissionCode;  //权限代码 length = 128

// 省略getter和setter。。。。


private Long permissionCodeHigh;
private Long permissionCodeLow;

/**
 * 获取访问权限码高64位
 * @date 2015-1-4
 * @return
 */
public long getPermissionCodeHigh() {
    if (this.permissionCodeHigh == null) {
        synchronized(this) {
            if (this.permissionCode != null&& this.permissionCode.matches("^[0-1]{128}$")) {

                permissionCodeHigh = Long.parseLong(this.permissionCode.substring(0, 64), 2);
            } else {

                permissionCodeHigh = new Long(0);
            }
        }    
    }

    return this.permissionCodeHigh.longValue();
}

/**
 * 获取访问权限码低64位
 * @date 2015-1-4
 * @return
 */
public long getPermissionCodeLow() {
    if (this.permissionCodeLow == null) {            
        synchronized(this) {                
            if (this.permissionCode != null&& this.permissionCode.matches("^[0-1]{128}$")) {

                permissionCodeLow = Long.parseLong(this.permissionCode.substring(64), 2);
            } else {

                permissionCodeLow = new Long(0);
            }
        }
    }
    return this.permissionCodeLow.longValue();
}

API权限码

API方法的权限码是用注解定义的。首先定义一个权限码的注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiredPermission {

    long high() default 0;

    long low() default 0;
}

使用注解定义权限码

@RequiredPermission(hight = 0,low = 1)
@RequestMapping(value = "/api/{sessionid}/tables", method = RequestMethod.GET)
public @ResponseBody
ResultInfo<List<InnerControlTable>> get(@PathVariable("sessionid") String sessionID)

此方法对应的128为权限码就是 000000….0000(127个0)1,每一个方法只能允许一位是1,其余位都必须为0,这样128为的权限码可以为128个方法定义权限。

拦截器处理

获取当前用户的权限集,再获取访问方法的权限码,如果两者相与结果为0,说明待访问的方法的权限码不在用户的权限集里,因此没有权限访问。

public class AuthorityInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {

        String url = request.getServletPath();    
        RequiredPermission annotation ;
        try{
               HandlerMethod handlerMethod = (HandlerMethod) handler;
               Method method = handlerMethod.getMethod();
               annotation = method.getAnnotation(RequiredPermission.class);
        }catch(ClassCastException e){
                return true;
        }

        if (annotation != null) {

            //与用户权限代码比较,有一个如果不为0,则说明有相应的权限。
            if ((annotation.low() & currUser.getPermissionCodeLow()) == 0 &&
                (annotation.high() & currUser.getPermissionCodeHigh()) == 0) {

                //没有权限,返回错误。
                PrintWriter out = response.getWriter();
                out.print(JsonBinder.getInstance().toJson(ResultInfo.getIllegalPermission()));

                out.flush();
                out.close();

                return false;

            }

        }

    }

        return true;
    }
}
本站总访问量