当使用shiro实现无状态应用程序时,是否需要每次请求都登录



我使用shiro和jwt,并尝试实现一个无状态的web应用程序
当我扩展AuthorizingRealm时,是否需要每次请求都使用executeLogin

这是我的executeLogin方法:

public static boolean executeLogin(ServletRequest request) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String authorization = httpServletRequest.getHeader("Authorization");
if (authorization == null || "".equals(authorization.trim())) {
throw RequestException.fail("未含授权标示,禁止访问");
}
JwtToken token = new JwtToken(authorization, null, null);
// 提交给realm进行登入,如果错误他会抛出异常并被捕获
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
} catch (DisabledAccountException e) {
if (e.getMessage().equals("verifyFail")) {
throw new RequestException(ResponseCode.NOT_SING_IN.code, "身份已过期,请重新登录", e);
}
throw new RequestException(ResponseCode.SIGN_IN_INPUT_FAIL.code, e.getMessage(), e);
} catch (Exception e) {
e.printStackTrace();
throw new RequestException(ResponseCode.SIGN_IN_FAIL, e);
}
// 如果没有抛出异常则代表登入成功,返回true
return true;
}

无状态表示每个请求不依赖于前一个请求,但这并不意味着Shiro不使用会话。

当用户成功登录时,Shiro会将一些cookie附加到HTTPResponse。当客户端向每个进一步的请求发送cookie时,Shiro会自动提取Subject(将cookie与用户关联(,因此,在您的代码中,您可以立即调用SecurityUtils.getSubject()

领域在这里是错误的方法,因为根据定义,它通常与数据源具有1对1的相关性。您实际想要做的是控制对服务器资源的访问,从客户端验证JWT。这可以通过AccessControlFilter来完成,读取授权标头并在过滤器isAccessAllowed方法中验证其声明。方法返回值定义是否允许访问。

您根本不需要登录主题,因为AccessControlFilter决定是授予还是拒绝访问,或者将用户转发到请求的资源,或者重定向401-未经授权的响应。

是的,您应该为每个请求登录。这将把主题附加到当前线程,并允许您使用特性:比如使用authz的注释。

当您使用无状态调用时,每次都必须登录并生成新的主题,还必须使用适当的领域加载授权详细信息。

您可以尝试的另一个选项是,登录成功后将主题放入缓存(ehCache(,然后在每次请求时,您可以从缓存中获取主题并用于授权。这将避免在每次请求时都填充登录和授权对象。但您必须确保在注销事件时从缓存中删除对象。

类似的事情已经由一位用户完成:

https://github.com/jikechenhao/springmvc-shiro-react-redux-restful-example

最新更新