一个项目的使用权限我们在前端做了一定限制,限制了用户可以看到的菜单栏;但是在后端并没有做太多限制,用户可以调所有接口,不管能不能看见这个界面。所以我们要在后端对用户拥有的界面权限做接口限制。
这个注解可以作用于类上:对于该controller里的所有接口都做统一权限判断;作用于接口上:对该接口单独做判断。
对于不需要做验证的接口可以使用ignore忽视。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MenuAuth {
String value() default "";
boolean ignore() default false;
}
value:菜单名称,用菜单名称做权限校验,获取用户拥有的菜单列表,判断是否包含这个接口的注解value值,从而判断用户是否可以调用此接口。
ignore:是否忽略注解,若忽略则无需判断。
重点在这里:
import cn.chinatelecom.dxsc.park.authorization.properties.AuthConfigProperties;
import cn.chinatelecom.dxsc.park.authorization.remote.LoginUserClientFeign;
import cn.chinatelecom.dxsc.park.entity.R;
import cn.chinatelecom.dxsc.park.entity.center.MenuTree;
import cn.chinatelecom.dxsc.park.entity.model.LoginHelper;
import cn.chinatelecom.park.schedule.common.annotation.MenuAuth;
import com.alibaba.spring.web.servlet.handler.AnnotatedHandlerMethodHandlerInterceptorAdapter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.method.HandlerMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Component
public class MenuAuthVerifyInterceptor extends AnnotatedHandlerMethodHandlerInterceptorAdapter<MenuAuth> {
@Autowired
private LoginUserClientFeign loginUserClientFeign;
@Autowired
private AuthConfigProperties authConfigProperties;
@Override
protected boolean preHandle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, MenuAuth menuAuth) throws Exception {
if (StringUtils.isBlank(request.getHeader("Authorization")))
return true;
if (menuAuth.ignore())
return true;
R<List<MenuTree>> userMenus = loginUserClientFeign.getUserMenus(LoginHelper.getLoginUser().getToken(), this.authConfigProperties.getClientId(), true);
List<MenuTree> menuTrees = userMenus.getData();
Set<String> menuNameSet = new HashSet<>();
if (!CollectionUtils.isEmpty(menuTrees)) {
menuTrees.forEach(menuTree -> addMenus(menuNameSet, menuTree));
}
//获取注解属性
String menuName = menuAuth.value();
if (!menuNameSet.contains(menuName)) {
throw new Exception("用户无对应权限");
}
return true;
}
private void addMenus(Set<String> menuName, MenuTree menuTree) {
menuName.add(menuTree.getName());
if (!CollectionUtils.isEmpty(menuTree.getChildren())) {
menuTree.getChildren().forEach(m -> {
addMenus(menuName, m);
});
}
}
}
在使用用户中心bean时,应该注意注入顺序,拦截器应该在用户中心后面,以免使用不了用户中心接口,获取不到用户的菜单列表。
首先,要验证是否携带token,该接口是否选择忽视。然后获取该token所拥有的菜单列表,获取注解value,判断菜单列表是否包含注解value。
然后拦截器主要注入(拦截顺序在用户中心后面):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MenuAuthVerifyInterceptorConfig implements WebMvcConfigurer {
@Autowired
MenuAuthVerifyInterceptor menuAuthVerifyInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(menuAuthVerifyInterceptor).order(1);
}
}
添加注解:
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-webmvc-support</artifactId>
<version>1.0.1</version>
</dependency>
如何使用:
该controller中的所有接口都会在“班次管理”这个菜单中,所以可以做统一鉴权。若其中的接口无需鉴权,则在其中的接口上单独添加@MenuAuth(ignore = true)即可。
简易的鉴权就做好了。
一个集坚强与自信于一身的菇凉。