package com.ruoyi.web.controller.tool;
|
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.exception.ServiceException;
|
import okhttp3.Request;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
import java.io.IOException;
|
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.Method;
|
import java.util.Collections;
|
import java.util.LinkedHashMap;
|
import java.util.Map;
|
|
/**
|
* 中台请求认证头回归测试。
|
*/
|
public class BaseDataApiUtilAuthorizationTest
|
{
|
public static void main(String[] args) throws Exception
|
{
|
shouldSkipAuthorizationForLogin();
|
shouldAddAuthorizationForMiddlePlatformRequest();
|
shouldAllowExplicitAuthorizationHeader();
|
shouldRequireReloginForExpiredMiddlePlatformSession();
|
shouldForbidLocalFallbackSession();
|
}
|
|
private static void shouldSkipAuthorizationForLogin() throws IOException
|
{
|
SecurityContextHolder.clearContext();
|
Request.Builder builder = requestBuilder();
|
addHeaders(builder, BaseDataApiUtil.Api.POST_AUTH_USER_LOGIN, null);
|
|
require(builder.build().header("Authorization") == null, "中台登录请求不应携带认证头");
|
}
|
|
private static void shouldAddAuthorizationForMiddlePlatformRequest() throws IOException
|
{
|
LoginUser loginUser = new LoginUser();
|
loginUser.setMiddlePlatformToken("middle-token");
|
SecurityContextHolder.getContext().setAuthentication(
|
new UsernamePasswordAuthenticationToken(loginUser, null, Collections.emptyList()));
|
|
Request.Builder builder = requestBuilder();
|
addHeaders(builder, BaseDataApiUtil.Api.GET_REGION_TREE, null);
|
|
require("Bearer middle-token".equals(builder.build().header("Authorization")),
|
"中台业务请求未携带正确的 Bearer Token");
|
SecurityContextHolder.clearContext();
|
}
|
|
private static void shouldAllowExplicitAuthorizationHeader() throws IOException
|
{
|
SecurityContextHolder.clearContext();
|
Map<String, String> headers = new LinkedHashMap<>();
|
headers.put("Authorization", "Bearer explicit-token");
|
Request.Builder builder = requestBuilder();
|
|
addHeaders(builder, BaseDataApiUtil.Api.POST_AUTH_USER_LOGOUT, headers);
|
|
require("Bearer explicit-token".equals(builder.build().header("Authorization")),
|
"显式中台认证头未被保留");
|
}
|
|
private static void shouldRequireReloginForExpiredMiddlePlatformSession()
|
{
|
SecurityContextHolder.clearContext();
|
try
|
{
|
addHeaders(requestBuilder(), BaseDataApiUtil.Api.GET_REGION_TREE, null);
|
throw new AssertionError("缺少中台 Token 时请求未被拒绝");
|
}
|
catch (ServiceException e)
|
{
|
require(Integer.valueOf(401).equals(e.getCode()), "中台认证失效时未返回401");
|
}
|
catch (IOException e)
|
{
|
throw new AssertionError("中台认证失效时异常类型错误", e);
|
}
|
}
|
|
private static void shouldForbidLocalFallbackSession()
|
{
|
LoginUser loginUser = new LoginUser();
|
loginUser.setLoginSource("local");
|
SecurityContextHolder.getContext().setAuthentication(
|
new UsernamePasswordAuthenticationToken(loginUser, null, Collections.emptyList()));
|
try
|
{
|
addHeaders(requestBuilder(), BaseDataApiUtil.Api.GET_REGION_TREE, null);
|
throw new AssertionError("本地回落账号访问中台数据时请求未被拒绝");
|
}
|
catch (ServiceException e)
|
{
|
require(Integer.valueOf(403).equals(e.getCode()), "本地回落账号访问中台数据时未返回403");
|
}
|
catch (IOException e)
|
{
|
throw new AssertionError("本地回落账号访问中台数据时异常类型错误", e);
|
}
|
finally
|
{
|
SecurityContextHolder.clearContext();
|
}
|
}
|
|
private static Request.Builder requestBuilder()
|
{
|
return new Request.Builder().url("http://localhost/test");
|
}
|
|
private static void addHeaders(Request.Builder builder, BaseDataApiUtil.Api api,
|
Map<String, String> headers) throws IOException
|
{
|
try
|
{
|
Method method = BaseDataApiUtil.class.getDeclaredMethod(
|
"addHeaders", Request.Builder.class, BaseDataApiUtil.Api.class, Map.class);
|
method.setAccessible(true);
|
method.invoke(null, builder, api, headers);
|
}
|
catch (InvocationTargetException e)
|
{
|
if (e.getCause() instanceof IOException)
|
{
|
throw (IOException) e.getCause();
|
}
|
if (e.getCause() instanceof RuntimeException)
|
{
|
throw (RuntimeException) e.getCause();
|
}
|
throw new IllegalStateException(e.getCause());
|
}
|
catch (ReflectiveOperationException e)
|
{
|
throw new IllegalStateException(e);
|
}
|
}
|
|
private static void require(boolean condition, String message)
|
{
|
if (!condition)
|
{
|
throw new AssertionError(message);
|
}
|
}
|
}
|