需求描述:
- 用户在未登录时访问网站中某个需要登录后才能访问的URL
- 请求被拦截跳转登陆页面
- 登陆后跳转未登录时访问的路径
具体实现:
1.拦截器 配置文件shiro.ini
[urls]
/usr/info/** = authc2
[filters]
authc2=com.fiter.FormAuthenticationFilter2
解释:
(1)filters指代自定义拦截器
authc2=com.fiter.FormAuthenticationFilter2,其中等号右侧为自定义拦截器代码,左侧为
指代
(2)urls指代需要进行拦截的URI
若该访问路径的URI需要有某种限制即需要被拦截器过滤下,即配制该拦截器
2.自定义拦截器
public class FormAuthenticationFilter2 extends FormAuthenticationFilter {
private static final Logger log = LoggerFactory.getLogger(FormAuthenticationFilter2.class);//定义日志输出
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
}
return executeLogin(request, response);
} else {
if (log.isTraceEnabled()) {
log.trace("Login page view.");
}
//allow them to see the login page ;)
return true;
}
} else {
if (log.isTraceEnabled()) {
log.trace("Attempting to access a path which requires authentication. Forwarding to the " + "Authentication url [" + getLoginUrl() + "]");
}
HttpServletRequest httpRequest = WebUtils.toHttp(request);
// 组装URL
StringBuilder returnUrl = new StringBuilder("http://t.com");
returnUrl.append(httpRequest.getRequestURI());
Enumeration enumeration = httpRequest.getParameterNames();
if(enumeration != null) {
boolean first = true;
while(enumeration.hasMoreElements()) {
Object param = enumeration.nextElement();
if(param != null && httpRequest.getParameter(param.toString()) != null) {
if(first) {
returnUrl.append("?");
}
returnUrl.append(param).append("=").append(httpRequest.getParameter(param.toString())).append("&");
first = false;
}
}
}
String encodedReturnUrl = returnUrl.toString();
if(encodedReturnUrl.endsWith("&")) {
encodedReturnUrl = encodedReturnUrl.substring(0, encodedReturnUrl.length() - 1);
}
encodedReturnUrl = URLEncoder.encode(encodedReturnUrl, "UTF-8");
StringBuilder builder = new StringBuilder("/login/loginpage.do?returnUrl=");
builder.append(encodedReturnUrl);
setLoginUrl(builder.toString());
redirectToLogin(request, response);
return false;
}
}
}
解释:
(1)request.getHeader("Referer"))获取上次访问的URL链接
a.原理:referer是浏览器在用户提交请求当前页面中的一个链接时,将当前页面的URL放在头
域中提交给服务端的,如当前页面为a.html,它里面有一个b.html的链接,当用户要访问b.html
时浏览器就会把a.html作为referer发给服务端.
b.限制:request.getHeader("Referer")要走HTTP协议才有值,也就是说要通过<a
href="url" />标记,才能获取到值。当然通过表单提交的也可以。而通过location或是<a
href="javascript:window.location=''" />是得不到值的
c.由于此处访问时未通过HTTP协议,故通过该方式获取的结果为空
(2)拦截器组装拦截后跳转的URL
3.实现效果
匿名访问:
http://localhost:8080/m2b/usr/info/getuserinfo.do
拦截跳转:
http://localhost:8080/m2b/login/loginpage.do?returnUrls=http%3A%2F%2Ft.com%2Fm2b%2Fusr%2Finfo%2Fgetuserinfo.do
该跳转URL为拦截器指定
4.跳转登陆
@Action(value = "loginpage", results = {
@Result(name = ResultTypeConstants.REDIRECT, type = ResultTypeConstants.REDIRECT, location = "/login/index.do"),
@Result(name = ResultTypeConstants.ISSUE_REDIRECT, type = ResultTypeConstants.REDIRECT, location = "/login/issueredirect.do"),
@Result(name = SUCCESS, type = ResultTypeConstants.VELOCITY, location = "/login.vm") })
@SkipValidation
public String loginpage() {
returnurl = request.getParameter("returnUrl");
if(returnurl == null) {
returnurl = request.getHeader("Referer");
}
logger.info("returnUrl:" + returnurl);
request.getSession().setAttribute("returnUrl", returnurl);
// 用户已登录
Subject currentUser = SecurityUtils.getSubject();
if (currentUser != null && currentUser.isAuthenticated()) {
return ResultTypeConstants.REDIRECT;
}
if (currentUser != null && currentUser.isRemembered()) {
user = (User) currentUser.getPrincipal();
rememberme = "1";
}
return SUCCESS;
}
解释:
(1)request.getParameter("returnUrl");获取拦截器组装的指定的URL中的参数,即http://t.com?returnUrl=http%3A%2F%2Fwww.dhport.com%2Fm2b%2Fusr%2Finfo%2Fgetuserinfo.do
(2)request.getParameter("");的使用
a.获取URL中的参数
b.获取页面通过submit方式传值
<form. name="form1" method="post" action="authenticate.jsp">
请输入用户姓名:<input type="text" name="username">
<input type="submit" name="Submit" value="提交">
</form>