# 接口鉴权

# 鉴权流程

  • 需要让自身框架对magic-api生成出来的接口给与放行,交给自己写的拦截器来实现。
  • 在页面上配置接口选项
  • 编写拦截器来实现接口鉴权

Spring Security为例,对magic-api生成出的接口放行示例

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.FilterInvocation;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.ssssssss.magicapi.controller.RequestHandler;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
public class MagicAPIAccessDecisionManager implements org.springframework.security.access.AccessDecisionManager {

    private final RequestMappingHandlerMapping requestMappingHandlerMapping;

    public PdAccessDecisionManager(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }

    @Override
    public void decide(Authentication authentication, Object object,
                       Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {

        FilterInvocation invocation = (FilterInvocation) object;
        HttpServletRequest request = invocation.getHttpRequest();
        Object handler = null;
        try {
            handler = requestMappingHandlerMapping.getHandler(request).getHandler();
        } catch (Exception ignored) {
        }
        if(handler != null && handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 提取处理类,判断是否是`magic-api`的处理器
            if(RequestHandler.class == handlerMethod.getBean().getClass()){
                return;
            }
        }
        String token = request.getHeader("token");
        if (StringUtils.isNotBlank(token)) {
            return;
        }
        if(configAttributes.stream()
                .map(Object::toString)
                .anyMatch(it -> it.equals("permitAll") || it.equals("anonymous"))){
            return;
        }
        throw new AccessDeniedException("Access is denied.");
    }
    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
@Autowired
RequestMappingHandlerMapping requestMappingHandlerMapping;

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception{
	// 其它配置省略...自行视情况配置。
    httpSecurity.authorizeRequests()
        .accessDecisionManager(new MagicAPIAccessDecisionManager(requestMappingHandlerMapping))
}
1
2
3
4
5
6
7
8
9

# 配置接口选项

接口选项

# 配置权限校验

/**
 * magic-api 接口鉴权
 */
@Component
public class CustomRequestInterceptor implements RequestInterceptor {

	private static final Logger logger = LoggerFactory.getLogger(CustomRequestInterceptor.class);

	/**
	 * 接口请求之前
	 * @param info	接口信息
	 * @param context	脚本变量信息
	 */
	@Override
	public Object preHandle(ApiInfo info, MagicScriptContext context, HttpServletRequest request, HttpServletResponse response) throws Exception {
		User user = null; // = XXXUtils.getUser(request);
		logger.info("{} 请求接口:{}", user, info.getName());
		// 接口选项配置了需要登录
		if ("true".equals(info.getOptionValue(Options.REQUIRE_LOGIN))) {
			if (user == null) {
				return new JsonBean<>(401, "用户未登录");
			}
		}
		String role = info.getOptionValue(Options.ROLE);
		if (StringUtils.isNotBlank(role) && user.hasRole(role)) {
			return new JsonBean<>(403, "用户权限不足");
		}
		String permission = info.getOptionValue(Options.PERMISSION);
		if (StringUtils.isNotBlank(permission) && user.hasPermission(permission)) {
			return new JsonBean<>(403, "用户权限不足");
		}
		return null;
	}

	/**
	 * 接口执行之后
	 * @param info	接口信息
	 * @param context	变量信息
	 * @param value 即将要返回到页面的值
	 */
	@Override
	public Object postHandle(ApiInfo info, MagicScriptContext context, Object value, HttpServletRequest request, HttpServletResponse response) throws Exception {
		logger.info("{} 执行完毕,返回结果:{}", info.getName(), value);
		return null;
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
上次更新: 8/29/2021, 8:57:58 AM
赞助商