1、自定义FormAuthenticationFilter
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 扩展FormAuthenticationFilter实现动态改变LoginUrl
*/
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {
/**
* 重写登录地址
*/
@Override
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
HttpServletRequest req = (HttpServletRequest) request;
String loginUrl = getLoginUrl();
String url = req.getRequestURI();
if (url.contains("/app/")) {
loginUrl = "/unauth";
}
WebUtils.issueRedirect(request, response, loginUrl);
}
}
自定义LogoutFilter
/**
* 扩展LogoutFilter实现动态改变redirectUrl
*/
public class CustomLogoutFilter extends LogoutFilter {
private static final Logger log = LoggerFactory.getLogger(CustomLogoutFilter.class);
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
Subject subject = this.getSubject(request, response);
if (this.isPostOnlyLogout() && !WebUtils.toHttp(request).getMethod().toUpperCase(Locale.ENGLISH).equals("POST")) {
return this.onLogoutRequestNotAPost(request, response);
} else {
try {
subject.logout();
} catch (SessionException var6) {
log.debug("Encountered session exception during logout. This can generally safely be ignored.", var6);
}
String redirectUrl = "/unauth";
this.issueRedirect(request, response, redirectUrl);
return false;
}
}
}
2、在ShiroConfig.java中的shiroFilter方法注入自定义FormAuthenticationFilter
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 获取filters
Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
// 将自定义的FormAuthenticationFilter注入shiroFilter中
filters.put("authc", new CustomFormAuthenticationFilter());
// 将自定义的LogoutFilter注入shiroFilter中
filters.put("logout", new CustomLogoutFilter());
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 拦截器.
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// 配置不会被拦截的链接 顺序判断
// 访问上传文件地址--start
filterChainDefinitionMap.put("/avatar/**", "anon");
filterChainDefinitionMap.put("/moodfile/**", "anon");
// 访问上传文件地址--end
filterChainDefinitionMap.put("/*.html", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/assets/**", "anon");
filterChainDefinitionMap.put("/images/**", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/verifcode/send", "anon");
filterChainDefinitionMap.put("/unauth", "anon");
filterChainDefinitionMap.put("/register", "anon");
filterChainDefinitionMap.put("/fpwd", "anon");
filterChainDefinitionMap.put("/login", "anon");
// 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了,登出后跳转配置的loginUrl
filterChainDefinitionMap.put("/logout", "logout");
// <!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
filterChainDefinitionMap.put("/**", "authc");
// 配置shiro默认登录界面地址,前后端分离中登录界面跳转应由前端路由控制,后台仅返回json数据
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("login.html");
// shiroFilterFactoryBean.setLoginUrl("/unauth");
// 登录成功后要跳转的链接
// shiroFilterFactoryBean.setSuccessUrl("/index");
// 未授权界面;
// shiroFilterFactoryBean.setUnauthorizedUrl("/403");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
参考:http://longload.iteye.com/blog/2278453
http://lib.csdn.net/article/java/65420?knId=1400