springBoot前后端分離項(xiàng)目中shiro的302跳轉(zhuǎn)問(wèn)題
springBoot前后端分離項(xiàng)目shiro的302跳轉(zhuǎn)
項(xiàng)目是使用的springboot ,使用的shiro做的用戶鑒權(quán)。在前端請(qǐng)求時(shí)當(dāng)用戶信息失效,session失效的時(shí)候,shiro會(huì)重定向到配置的login.jsp 頁(yè)面,或者是自己配置的logUrl。
因是前后端分離項(xiàng)目,與靜態(tài)資源文件分離,固重定向后,接著會(huì)404。
經(jīng)過(guò)查找網(wǎng)上配置資料,發(fā)現(xiàn)302原因是
- FormAuthenticationFilter中onAccessDenied 方法做了相應(yīng)處理。那知道問(wèn)題所在,就可以有解決方了。
- 重寫 onAccessDenied 方法,針對(duì)自己的業(yè)務(wù)做相應(yīng)處理,然后在加載過(guò)濾器配置的時(shí)候添加到配置中。
以下是代碼
增加類ShiroFormAuthenticationFilter 重新方法
package com.oilpay.wallet.shiro;
import com.alibaba.fastjson.JSONObject;
import com.oilpay.wallet.interceptor.TokenInterceptor;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
/**
*
* 重寫權(quán)限驗(yàn)證問(wèn)題,登錄失效后返回狀態(tài)碼
*
*/
public class ShiroFormAuthenticationFilter extends FormAuthenticationFilter {
Logger logger = LoggerFactory.getLogger(TokenInterceptor.class);
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
if (logger.isTraceEnabled()) {
logger.trace("Login submission detected. Attempting to execute login.");
}
return executeLogin(request, response);
} else {
if (logger.isTraceEnabled()) {
logger.trace("Login page view.");
}
//allow them to see the login page ;)
return true;
}
} else {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse) response;
if(req.getMethod().equals(RequestMethod.OPTIONS.name())) {
resp.setStatus(HttpStatus.OK.value());
return true;
}
if (logger.isTraceEnabled()) {
logger.trace("Attempting to access a path which requires authentication. Forwarding to the " +
"Authentication url [" + getLoginUrl() + "]");
}
//前端Ajax請(qǐng)求時(shí)requestHeader里面帶一些參數(shù),用于判斷是否是前端的請(qǐng)求
String test= req.getHeader("test");
if (test!= null || req.getHeader("wkcheck") != null) {
//前端Ajax請(qǐng)求,則不會(huì)重定向
resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
resp.setHeader("Access-Control-Allow-Credentials", "true");
resp.setContentType("application/json; charset=utf-8");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
JSONObject result = new JSONObject();
result.put("message", "登錄失效");
result.put("resultCode", 1000);
out.println(result);
out.flush();
out.close();
} else {
saveRequestAndRedirectToLogin(request, response);
}
return false;
}
}
}
在過(guò)濾器配置中添加
@Bean(name="shiroFilter")
public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager manager) {
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(manager);
//配置訪問(wèn)權(quán)限
LinkedHashMap<String, String> filterChainDefinitionMap=new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/common/logout", "logout");
filterChainDefinitionMap.put("/","anon");
filterChainDefinitionMap.put("/common/login","anon");
filterChainDefinitionMap.put("/common/*","anon");
filterChainDefinitionMap.put("/imageVerifyCode/getCode", "anon");
filterChainDefinitionMap.put("/sendVerifyCode/register", "anon");
filterChainDefinitionMap.put("/sendVerifyCode/resetLoginPwd", "anon");
filterChainDefinitionMap.put("/**", "authc"); //表示需要認(rèn)證才可以訪問(wèn)
LinkedHashMap<String, Filter> filtsMap=new LinkedHashMap<String, Filter>();
filtsMap.put("authc",new ShiroFormAuthenticationFilter() );
shiroFilterFactoryBean.setFilters(filtsMap);
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
至此,可以按照自己的需求做相應(yīng)處理。
關(guān)于shiro 總是302的問(wèn)題
我的原因是使用了authc,由于autuc對(duì)應(yīng)的過(guò)濾器FormAuthenticationFilter中onAccessDenied方法返回的值都為false,所以訪問(wèn)url時(shí)會(huì)一直進(jìn)行循環(huán)重定向,解決方案:重寫onAccessDenied方法,并注入到shiroFiter中。
附上shiro配置文件
<!-- shiroFilter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<!-- 設(shè)定角色的登錄鏈接,這里為cas登錄頁(yè)面的鏈接可配置回調(diào)地址 -->
<!-- 登錄地址 -->
<property name="loginUrl" value="/login.html"/>
<!-- 登錄后跳轉(zhuǎn)到業(yè)務(wù)頁(yè)面 -->
<property name="successUrl" value="/index.do"/>
<!-- 錯(cuò)誤頁(yè)面 -->
<property name="unauthorizedUrl" value="/denied.html"/>
<property name="filters">
<map>
<!--將重寫了的FormAuthenticationFilter.onAccessDenied方法的類注入到其中-->
<entry key="authc" value-ref="formAuthenticationFilter"></entry>
</map>
</property>
<property name="filterChainDefinitions">
<value>
/login.html=anon
<!--配置靜態(tài)資源-->
/js/**=anon
/templates/**=anon
/assets/**=anon
/css/**=anon
<!--權(quán)限設(shè)置-->
/index.do=authc
/user/login.do=anon
/**=authc
</value>
</property>
</bean>
<!-- 重寫FormAuthenticationFilter的onAccessDenied方法的自定義過(guò)濾器 -->
<bean id="formAuthenticationFilter" class="com.jd.risk.giasys.service.realm.filter.MyFilter" />
重寫onAccessDenied方法
package com.jd.risk.giasys.service.realm.filter;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* Created by jianghaisong on 2017/12/17.
*/
public class MyFilter extends FormAuthenticationFilter{
private Logger log = LoggerFactory.getLogger(MyFilter.class);
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
//進(jìn)行重寫,業(yè)務(wù)邏輯
}
}
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 使用React和springboot做前后端分離項(xiàng)目的步驟方式
- SpringBoot+mybatis+Vue實(shí)現(xiàn)前后端分離項(xiàng)目的示例
- IDEA教程創(chuàng)建SpringBoot前后端分離項(xiàng)目示例圖解
- SpringBoot+MyBatisPlus+Vue 前后端分離項(xiàng)目快速搭建過(guò)程(后端)
- 部署vue+Springboot前后端分離項(xiàng)目的步驟實(shí)現(xiàn)
- 使用Springboot+poi上傳并處理百萬(wàn)級(jí)數(shù)據(jù)EXCEL
- Springboot+Poi導(dǎo)入Excel表格實(shí)現(xiàn)過(guò)程詳解
- Springboot?前后端分離項(xiàng)目使用?POI?生成并導(dǎo)出?Excel的操作方法
相關(guān)文章
idea啟動(dòng)報(bào)錯(cuò):Command line is too long問(wèn)題
在使用IDEA時(shí),若遇到"Commandlineistoolong"錯(cuò)誤,通常是因?yàn)槊钚虚L(zhǎng)度超限,這是因?yàn)镮DEA通過(guò)命令行或文件將classpath傳遞至JVM,操作系統(tǒng)對(duì)命令行長(zhǎng)度有限制,解決方法是切換至動(dòng)態(tài)類路徑,通過(guò)修改項(xiàng)目的workspace.xml文件2024-09-09
JavaWeb學(xué)習(xí)過(guò)程之MVC查詢模式詳解
這篇文章主要介紹了JavaWeb學(xué)習(xí)過(guò)程之MVC查詢模式詳解的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09
SPRING BOOT啟動(dòng)命令參數(shù)及源碼詳析
這篇文章主要給大家介紹了關(guān)于SPRING BOOT啟動(dòng)命令參數(shù)及源碼分析的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用SPRING BOOT具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
java中@ConfigurationProperties失效的問(wèn)題解決
在Java開發(fā)中,使用@ConfigurationProperties注解讀取配置文件時(shí),如果配置類中的屬性設(shè)置為static,將無(wú)法正確讀取配置值,本文就來(lái)介紹一下具體解決方法,感興趣的可以了解一下2024-09-09
寫了兩年代碼之后再來(lái)談一談Spring中的Bean
這篇文章主要介紹了寫了兩年代碼之后再來(lái)看看Spring中的Bean,這里列出四種常用的添加Bean的方式,介紹最基本的@Bean注解,@Bean注解聲明這個(gè)類是一個(gè)Bean,需要的朋友可以參考下2021-10-10

