Heim > Java > javaLernprogramm > Hauptteil

Methoden zum Umschreiben und Konfigurieren von Shiro-Filtern in SpringBoot

WBOY
Freigeben: 2023-05-15 10:10:06
nach vorne
1443 Leute haben es durchsucht

Problem

Es ist ein Problem aufgetreten: In einem Projekt, das den domänenübergreifenden Zugriff vom Front- und Backend trennt, schlägt das Abfangen von Berechtigungen durch Shiro fehl (selbst der Zugriff mit korrekten Berechtigungen wird abgefangen), was zu Problemen wie 302-Umleitungsfehlern führt.
Fehlerbericht: Antwort für Preflight ist ungültig (Umleitung)

1.302 Grund: Der Umleitungsvorgang kann nicht erkannt werden, wenn Ajax für den Zugriff auf das Back-End-Projekt verwendet wird

2.Shiro-Interception-Fehlergrund: Es gibt einen domänenübergreifenden Preflight-Zugriff während Domänenzugriff, das heißt, beim Zugriff wird zuerst eine Nachricht gesendet. Die Zugriffsmethoden sind OPTIONEN, und dieser Zugriff umfasst keine Cookies und andere Informationen. Dies führt dazu, dass Shiro fälschlicherweise annimmt, dass der Zugriff ohne Erlaubnis erfolgt.

3. Im Allgemeinen werden folgende Zugriffsmethoden verwendet: „Get“, „Post“, „Put“, „Delete“

1. Lassen Sie Shiro den Zugriff nicht vorab überprüfen in, was das Umschreiben mehrerer Filter erfordert

3. Konfigurieren Sie die neu geschriebenen Filter

Implementierungscode

1. Schreiben Sie den Shiro-Anmeldefilter neu

Filterbetriebsmechanismus:

(1) Ob Shiro den Zugriff abfängt, basiert auf dem Rückgabewert von isAccessAllowed

(2) Wenn die isAccessAllowed-Methode „false“ zurückgibt, wird die onAccessDenied-Methode eingegeben und zur Anmelde- oder Nichtberechtigungsseite weitergeleitet

package com.yaoxx.base.shiro;

import java.io.PrintWriter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.http.HttpStatus;

/**
*  
* @version: 1.0
* @since: JDK 1.8.0_91
* @Description:
* 		未登录过滤器,重写方法为【跨域的预检访问】放行

*/

public class MyAuthenticationFilter extends FormAuthenticationFilter {
   
   @Override
   protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
   	boolean allowed = super.isAccessAllowed(request, response, mappedValue);
   	if (!allowed) {
   		// 判断请求是否是options请求
   		String method = WebUtils.toHttp(request).getMethod();
   		if (StringUtils.equalsIgnoreCase("OPTIONS", method)) {
   			return true;
   		}
   	}
   	return allowed;
   }

   @Override
   protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
   	if (isLoginRequest(request, response)) { // 判断是否登录
   		if (isLoginSubmission(request, response)) { // 判断是否为post访问
   			return executeLogin(request, response);
   		} else {
   			// sessionID已经注册,但是并没有使用post方式提交
   			return true;
   		}
   	} else {
   		HttpServletRequest req = (HttpServletRequest) request;
   		HttpServletResponse resp = (HttpServletResponse) response;
   		/*
   		 * 跨域访问有时会先发起一条不带token,不带cookie的访问。
   		 * 这就需要我们抓取这条访问,然后给他通过,否则只要是跨域的访问都会因为未登录或缺少权限而被拦截
   		 * (如果重写了isAccessAllowed,就无需下面的判断)
   		 */
//			if (req.getMethod().equals(RequestMethod.OPTIONS.name())) {
//				resp.setStatus(HttpStatus.OK.value());
//				return true;
//			}
   		/*
   		 * 跨域的第二次请求就是普通情况的request了,在这对他进行拦截
   		 */
   		String ajaxHeader = req.getHeader(CustomSessionManager.AUTHORIZATION);
   		if (StringUtils.isNotBlank(ajaxHeader)) {
   			// 前端Ajax请求,则不会重定向
   			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");
   			resp.setStatus(HttpStatus.UNAUTHORIZED.value());//设置未登录状态码
   			PrintWriter out = resp.getWriter();
//				Map<String, String> result = new HashMap<>();
//				result.put("MESSAGE", "未登录用户");
   			String result = "{"MESSAGE":"未登录用户"}";
   			out.println(result);
   			out.flush();
   			out.close();
   		} else {
   			// == 如果是普通访问重定向至shiro配置的登录页面 == //
   			saveRequestAndRedirectToLogin(request, response);
   		}
   	}
   	return false;
   }
}
Nach dem Login kopieren

2. Konfigurieren Sie den Filter

package com.yaoxx.base.shiro;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;

/**
* 
* @author: yao_x_x
* @since: JDK 1.8.0_91
* @Description: role的过滤器
*/

public class MyAuthorizationFilter extends RolesAuthorizationFilter {

   @Override
   public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
   		throws IOException {
   	boolean allowed =super.isAccessAllowed(request, response, mappedValue);
   	if (!allowed) {
   		String method = WebUtils.toHttp(request).getMethod();
   		if (StringUtils.equalsIgnoreCase("OPTIONS", method)) {
   			return true;
   		}
   	}
   	return allowed;
   }

   @Override
   protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
   	HttpServletRequest req = (HttpServletRequest) request;
   	HttpServletResponse resp = (HttpServletResponse) response;
   	if (req.getMethod().equals(RequestMethod.OPTIONS.name())) {
   		resp.setStatus(HttpStatus.OK.value());
   		return true;
   	}
   	// 前端Ajax请求时requestHeader里面带一些参数,用于判断是否是前端的请求
   	String ajaxHeader = req.getHeader(CustomSessionManager.AUTHORIZATION);
   	if (StringUtils.isNotBlank(ajaxHeader)) {
   		// 前端Ajax请求,则不会重定向
   		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();
   		String result = "{"MESSAGE":"角色,权限不足"}";
   		out.println(result);
   		out.flush();
   		out.close();
   		return false;
   	}
   	return super.onAccessDenied(request, response);
   }
}
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonMethoden zum Umschreiben und Konfigurieren von Shiro-Filtern in SpringBoot. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:yisu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!