shiro 會話超時302問題

  產生異常的狀況:nginx配置了https,可是nginx轉發請求到web應用走的http,會話超時,shiro會重定向到登陸頁,這時重定向的是http地址,好比http://xxxxx/login/index ,瀏覽器會阻止這樣的請求(從https頁面發起http請求是非法的)。javascript

  1. 重寫shiro的FormAuthenticationFilter
public class MyShiroAuthcFilter extends FormAuthenticationFilter {

	public MyShiroAuthcFilter(String loginUrl) {
		super();
		setLoginUrl(loginUrl);
	}

	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
		if (isLoginRequest(request, response)) {
			return super.onAccessDenied(request, response);
		} else {
			if (isAjax((HttpServletRequest) request)) { // 處理ajax請求
				HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
				httpServletResponse.addHeader("REQUIRE_AUTH", "true"); // ajax全局設置中有用
				httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value()); // 改變302狀態碼
			} else {
				saveRequest(request);
				request.getRequestDispatcher(getLoginUrl()).forward(request, response);
				// 因爲是nginx轉發的,redirect 302會重定向到http協議,不是瀏覽器指望的https
				// saveRequestAndRedirectToLogin(request, response);
			}
			return false;
		}
	}

	private boolean isAjax(HttpServletRequest request) {
		String requestedWithHeader = request.getHeader("X-Requested-With");
		return "XMLHttpRequest".equals(requestedWithHeader);
	}
}

shiro的filter配置java

@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
	String loginUrl = "/login/index";
	ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();

	Map<String, Filter> filters = shiroFilter.getFilters();
	filters.put("anon", new AnonymousFilter());
	filters.put("authc", new MyShiroAuthcFilter(loginUrl));

	Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
	filterChainDefinitionMap.put("/supervisor/**", "authc");
	filterChainDefinitionMap.put("/**", "anon");

	shiroFilter.setSecurityManager(securityManager);
	shiroFilter.setLoginUrl(loginUrl);
	shiroFilter.setUnauthorizedUrl("/login/unauthorized");
	shiroFilter.setFilters(filters);
	shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);

	return shiroFilter;
}
  1. ajax全局設置
$.ajaxSetup({
    complete: function (xhr, status) {
    	if (xhr.getResponseHeader('REQUIRE_AUTH') == 'true') {
    		alert("未登陸或登陸超時!");
    		window.top.location.href = getHost() + '/login/index';
    		return;
    	}
	}
});
  1. /login/index頁面處理
<script type="text/javascript">
	// 使登陸頁出如今「頂級」窗口,調整瀏覽器的url地址,上面的filter是forward到登陸頁的
	if(window.top != window.self || location.pathname != '/login/index') {
	window.top.location = getHost() + '/login/index';
	}
</script>
相關文章
相關標籤/搜索