最近做了Shiro与CAS的集成,第一次深入Shiro,发现Shiro是一个不错的安全框架,cas是另外一个搭建做的。
登录成功之后有3种页面跳转选择,这是根据触发登录操作的页面分类的。
1. 当前页面不需要登录即可访问,点击登录按钮,登陆成功之后留在本页面,特别是不再首页的情况
2. 用户访问的目标页面需要登陆之后才能访问,访问这种页面首先去登录页面,登录成功再自动去目标页面
3. 登录成功都跳转首页
一点警告,shiro与cas集成时shiro中配置的登录失败的地址不应该是cas的登录地址,如果这样配置是有问题的。
干货:
针对第3个:
shiro可以配置登录成功默认的跳转地址
正对第2个:
//首先配置的shiro filter会拦截到去目标页面的这个请求,filter如下重写方法即可解决
/*知道一个东西,配置的shiro的filter什么时候起作用,当用户没有登录的时候起作用。
如果用户登录了shiro filter会放过请求,不对请求做任何处理
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception{
String loginUrl = "casServerLoginUrl?service=xxx";
//起主要作用,保存当前的请求信息,登录成功之后再获取这个请求,根据这个请求指向的页面做跳转
org.apache.shiro.web.util.WebUtils.saveRequest(request);
//设置cas的登录地址,应该可以不用设置,因为在shiro-cas配置文件中做了设置
org.apache.shiro.web.util.WebUtils.issueRedirect(request, response, loginUrl);
return false;
}
针对第1个:
采用迂回的做法
首先在shiro配置文件中定义一个过滤路径 /api/shiro/login 这个路径使用上面第2个的过滤器过滤或单独定义(必须按照上面第2个重写方法)
<property name="filterChainDefinitions">
<value>
<!-- /account/login = authc -->
/shirocas = casFilter
/api/shiro/login = loginFilter
</value>
</property>
然后定义一个Controller 定义接口 /api/shiro/login
@RequestMapping(value="/api/shiro/login", method = RequestMethod.GET)
public Object login(HttpServletRequest request, HttpServletResponse response) {
String redirectUrl = request.getParameter("redirect");//页面登录按钮设置的请求参数
if (StringUtils.isBlank(redirectUrl)) {
redirectUrl = request.getContextPath();
}
try {
response.sendRedirect(redirectUrl);
} catch (IOException e) {
}
return null;
}
接着修改登录按钮跳转的地址
$("loginBtn").click(function() {window.location = '/api/shiro/login?redirect=' + window.location.href});
/*
原理:第一 shiro 的filter先于Controller拦截请求,第二 对登录状态下的请求shiro filter会放过,然后Controller拦截
shiro的filter(比如loginFilter)会先于Controller拦截到请求,loginFilter保存了当前的请求信息(即跳转的目标地址 /api/shiro/login),cas登录成功之后重定向到shiro的filter,shiro登录成功,然后通过org.apache.shiro.web.util.WebUtils.getAndClearSavedRequest(request)获取上次请求的信息,重定向到上次请求指向的路径即:/api/shiro/login?redirect=xxx. Controller 这个时候shiro的filter拦截这个请求,一看请求已经登录,放过,Controller(见上面)拦截,然后就成功啦
*/