Soul网关-day08
Soul-plugin-sofa测试(三)
接第7天的话题,可以看到token为null以后直接返回errorResponse的类为 StatelessAuthFilter。这个类是框架定义的,那么我们是在哪里将这个Filter集成进我们的shiro框架呢?
eclipse和idea中都提供了调用查询的功能,这里可以看到:是在org.dromara.soul.admin.shiro.config.ShiroConfiguration中的
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(
@Qualifier("shiroSecurityManager") final DefaultWebSecurityManager securityManager,
@Qualifier("whiteList") final List<String> whiteList)
这个方法将ShiroFilterFactoryBean交给Spring托管,在这个方法中定义了一个filterMap;将StatelessAuthFilter塞进这个map中(key为statelessAuth),再将这个map塞进factoryBean的filter中。这个Filter定义了过滤器的行为;紧接在后的就是定义过滤器的作用域了,具体实现代码如下:
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
for (String s : whiteList) {
filterChainDefinitionMap.put(s, "anon");
}
filterChainDefinitionMap.put("/**", "statelessAuth");
factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
可以看到,在上述代码中,whiteList中定义的所有路径都不进行过滤操作(anon),而除了whiteList中的所有路径,都需要经过statelessAuth这个过滤器的过滤,所以这就能解释为什么有些请求路径可以被直接访问,而有些路径则不行,而whiteList是在soul-admin的配置文件中进行配置的:
application.yml:
soul:
jwt:
key: 2095132720951327
shiro:
white-list: /,/favicon.*,/static/**,/index**,/plugin,/platform/**,/websocket,/configs/**,/soul-client/**
ShiroConfiguration中还定义了:securityManager,并将自定义的shiroRealm作为Realm塞进了securityManager;ShiroRealm中主要定义了两个方法:
protected AuthorizationInfo doGetAuthorizationInfo(final PrincipalCollection principalCollection)
protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken authenticationToken)
其中doGetAuthenticationInfo是在shiro登陆时被调用的
doGetAuthorizationInfo方法是在一下两个阶段被调用的:
1:调用SecurityUtils.getSubject().isPermitted(String str)方法时会调用doGetAuthorizationInfo方法,
2:在配置文件中配置有类似/**=roles["user"]或者/**=perms[“user”](/**路径是开发者自行定义)的配置的时候会调用doGetAuthorizationInfo方法,这个时候有两种情况:
2.1:当当前没有用户登录时shiro会帮我们跳转到login.jsp(默认会找根目录下的login.jsp)
2.2:当前有登录用户时shiro会自动判定当前登录用户的角色或者权限符合访问当前访问路径,如果不符合那么将跳转到开发者所配置的未授权提示页面( <property name="unauthorizedUrl" value="/unauthorized.jsp"/>),这种调用情下doGetAuthorizationInfo方法只会被调用一次,除非更换了当前登录用户。
而在ShiroRealm的doGetAuthenticationInfo方法可以看到:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken authenticationToken) {
StatelessToken token = (StatelessToken) authenticationToken;
if (token == null || token.getToken() == null) {
return null;
}
String userName = JwtUtils.getIssuer(token.getToken());
token.setUserName(userName);
return new SimpleAuthenticationInfo(userName, token.getToken(), this.getName());
}
从命名猜测,这里是将得到的 jwt token校验、解码后得到user的名称,为shiro管理的authenticationToken的userName属性赋予得到用户名。
但似乎确实没太大关联,抓包以后可以看到:
而whiteList上只配置了/plugin这个路径,这个请求路径:/plugin/all必然会被statelessAuth这个过滤器所拦截,在statelessAuth这个类上的onAccessDenied方法上的逻辑是:
//得到httpRequest
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
//判断是否为Options的请求,如果是,则直接返回true;
if (StringUtils.equals(HttpMethod.OPTIONS.name(), httpServletRequest.getMethod())) {
return true;
}
//从request中获取X-Access-Token这个属性
String tokenValue = httpServletRequest.getHeader(HEAD_TOKEN);
if (StringUtils.isBlank(tokenValue)) {
log.error("token is null.");
unionFailResponse(servletResponse);
return false;
}
//只有获取到了这个属性,才能构建出一个StatelessToken
StatelessToken token = new StatelessToken();
token.setToken(tokenValue);
Subject subject = getSubject(servletRequest, servletResponse);
try {
//用token进行登录
subject.login(token);
} catch (Exception e) {
log.error("token is warning. token : {}.", tokenValue, e);
unionFailResponse(servletResponse);
return false;
}
return true;
从上面的抓包很明显看出:并没有这个属性。大概需要求助了…问下如何构建这个request请求的。还不知道这个request请求到底哪出了问题…