Shiro(一)——Shrio增加token验证
项目需求:Shrio增加token验证。
需求分析:
1.Shrio的认证方式的流程:
登录Controller中,根据输入的账号和密码创建token,然后调用subject.login(token)方法,subject会委托给securityManager,由securityManager再执行login方法。
由ModularRealmAuthenticator调用realm的doGetAuthenticationInfo进行认证。如果不正确则抛出异常执行onFailedLogin()
2.基于session的登录认证
在ShiroFilterFactoryBean中可以添加Filter来验证是否已登录。
isAccessAllowed方法通过subject.getPrincipal()是否为空来判断该subject是否已登录。
getSubject()是从当前线程得到绑定的subject
那subject是什么时候创建的呢?
ShiroFilterFactoryBean里就包含了AbStractShiroFilter,每次请求的时候都会执行doFilterInternal里的createSubject,如何跟session绑定的呢?放到sessionManage里再分析,这里简单略过。subject会根据context来生成,而context中则包含了session。
每次请求都会重新设置Session和Principals,看到这里大概就能猜到:如果是web工程,直接从web容器获取httpSession,然后再从httpSession获取Principals,本质就是从cookie获取用户信息,然后每次都设置Principal,这样就知道是哪个用户的请求,并只得到这个用户有没有人认证成功,–本质:依赖于浏览器的cookie来维护session的。
实现方法:1.创建一个自己的realm用于验证第三方的token,继承AuthorizingRealm,需要supports方法来支持自定义的token。
public class MyRealm extends AuthorizingRealm {
public boolean supports(AuthenticationToken token) {
return token instanceof GylToken;
}//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
GylToken gylToken = (GylToken) token;
//发送http请求验证
//创建httpClient实例对象
HttpClient httpClient = new HttpClient();
// 设置httpClient连接主机服务器超时时间:15000毫秒
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(15000);
// 创建GET请求方法实例对象
GetMethod getMethod = new GetMethod("xxx");
// 设置post请求超时时间
getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 60000);
//getMethod.addRequestHeader("Content-Type", "application/json");
getMethod.setRequestHeader("token",(String) token.getCredentials());
try{
httpClient.executeMethod(getMethod);
String result = getMethod.getResponseBodyAsString();
JSONObject jsonObject=JSONObject.fromObject(result);
Map map = (Map)jsonObject;
if(map.get("flag")==null || (int)map.get("flag")!=1){
throw new UnknownAccountException("token无效");
}
}catch (Exception e){
e.printStackTrace();
}finally{
getMethod.releaseConnection();
}
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo("test", gylToken.getPrincipal(), getName());
return info;
}
}
2.有了认证还不够,还要添加Filter来拦截获取Token
重写onAccessDenied方法,isAccessAllowed失败,走onAccessDenied方法判断如果token为空则走正常途径,如果token不为空则走executeLogin,再调用subject.login(token)走自定义realm的认证方法。
protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
String token = getRequestToken((HttpServletRequest) servletRequest);
if (StringUtils.isBlank(token)) {
saveRequestAndRedirectToLogin(servletRequest, servletResponse);
return false;
}
return executeLogin(servletRequest, servletResponse);
}
【Shiro(一)——Shrio增加token验证】3.虽然这样已经满足了基本需求,但只能每次都走realm认证,没有用到shiro的核心完整的会话管理。
推荐阅读
- 一个人的旅行,三亚
- 急于表达——往往欲速则不达
- 慢慢的美丽
- 一个小故事,我的思考。
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量
- 开学第一天(下)
- 一个人的碎碎念
- 2018年11月19日|2018年11月19日 星期一 亲子日记第144篇
- 2019-02-13——今天谈梦想()
- 遇到一哭二闹三打滚的孩子,怎么办┃山伯教育