Heim  >  Artikel  >  Web-Frontend  >  Wie vue+springboot domänenübergreifende Single-Sign-On-Probleme implementiert (ausführliches Tutorial)

Wie vue+springboot domänenübergreifende Single-Sign-On-Probleme implementiert (ausführliches Tutorial)

亚连
亚连Original
2018-06-08 18:19:523186Durchsuche

In diesem Artikel wird hauptsächlich die Lösung des domänenübergreifenden Problems des Single Sign-On durch die Trennung von Vue + Springboot-Frontend und Back-End vorgestellt

Ich bin Derzeit wird an einem Back-End-Managementsystem gearbeitet. Das Front-End verwendet das aktuelle beliebte vue.js, das Backend basiert auf Springboot. Da das Backend-System keine Anmeldefunktion hat, das Unternehmen jedoch eine einheitliche Anmeldung benötigt, verwendet die Anmeldeauthentifizierung das Authentifizierungssystem des .net-Projektteams. Das bedeutet, dass Sie Single Sign-On durchführen müssen. Für Studierende, die nicht wissen, was Single Sign-On ist, empfehle ich Ihnen, sich an die Allzweck-App Du Niang zu wenden.

Als ich diese Anforderung zum ersten Mal erhielt, dachte ich mit Verachtung: Nur das Einloggen ist nicht wichtig. Der Entwicklungsprozess hat mich jedoch hart getroffen (eine heftige Ohrfeige). . . Deshalb muss ich diese Lektion dieses Mal gut aufzeichnen, um in Zukunft nicht in solche Fallstricke zu tappen.

Das erste Problem, mit dem ich konfrontiert war, war die domänenübergreifende Konfiguration von CORS. Mit meiner langjährigen Entwicklungserfahrung habe ich die domänenübergreifende Konfiguration wie folgt konfiguriert:

@Configuration
public class CorsConfiguration {
 @Bean
 public WebMvcConfigurer corsConfigurer() {
  return new WebMvcConfigurerAdapter() {
   @Override
   public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
      .allowedHeaders("*")
      .allowedMethods("*")
      .allowedOrigins("*");
   }
  };
 }
}

Diese Konfiguration ermöglicht alle Zuordnungen, alle Anforderungsheader, alle Anforderungsmethoden und alle Quellen. Nachdem ich die Konfiguration geändert hatte, habe ich das Projekt entschlossen neu gestartet, um den Effekt zu sehen. Da ich festgestellt habe, dass es keine Möglichkeit gibt, zur Single-Sign-In-Seite umzuleiten, habe ich zuerst den Code von hochgeladen mein Login-Interceptor

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 //用户已经登录
 if (request.getSession().getAttribute("user") != null) {
  return true;
 }
 //从单点登录返回之后的状态,本系统还不处于登录状态
 //根据code值去获取access_token,然后再根据access_token去获取用户信息,并将用户信息存到session中
 String state = request.getParameter("state");
 String uri = getUri(request);
 if (isLoginFromSSO(state)) {
  String code = request.getParameter("code");
  Object cacheUrl = request.getSession().getAttribute(state);
  if (cacheUrl == null) {
   response.sendRedirect(uri);
   return false;
  }
  HttpUtil client = new HttpUtil();
  StringBuffer sb = new StringBuffer();
  sb.append("code=").append(code)
    .append("&grant_type=").append("authorization_code")
    .append("&client_id=").append(SSOAuth.ClientID)
    .append("&client_secret=").append(SSOAuth.ClientSecret)
    .append("&redirect_uri=").append(URLEncoder.encode((String) cacheUrl));
  String resp = client.post(SSOAuth.AccessTokenUrl, sb.toString());
  Map<String, String> map = new Gson().fromJson(resp, Map.class);
  //根据access_token去获取用户信息
  String accessToken = map.get("access_token");
  HttpUtil http = new HttpUtil();
  http.addHeader("Authorization", "Bearer " + accessToken);
  String encrypt = http.get(SSOAuth.UserUrl);
  String userinfo = decryptUserInfo(encrypt);
  //封装成user对象
  User user = new Gson().fromJson(userinfo, User.class);
  request.getSession().setAttribute("user", user);
  return true;
 }
 //跳转到单点登录界面
 state = Const._SSO_LOGIN + Const.UNDERLINE + RandomUtil.getUUID();
 request.getSession().setAttribute(state, uri);
 String redirectUrl = buildAuthCodeUrl(uri, state);
 response.sendRedirect(redirectUrl);
 return false;
}

Der Front-End-Vue fordert die Back-End-Login-Schnittstelle direkt über

window.location.href=this.$api.config.baseUrl+"/system/user/login"

und dann das Frontend auf das System zugreift, können Sie direkt zur Single-Sign-On-Seite springen. Aber als ich mein Konto und mein Passwort eingegeben und auf „Anmelden“ geklickt habe, sprang ich zurück zum System und stellte fest, dass nicht auf alle Anforderungsdatenschnittstellen normal zugegriffen werden konnte. Debug stellte fest, dass alle Anforderungen keine Benutzerinformationen enthielten und vom Interceptor als erkannt wurden nicht angemeldet, daher konnten nicht alle Anfragen angenommen werden.

Warum setzt der Interceptor auch Benutzerinformationen für die Sitzung, obwohl ich angemeldet bin? Warum sind die Cookies verschwunden? Ich habe die Anfrage erneut initiiert und festgestellt, dass die JsessionId jeder Anfrage unterschiedlich war. Ich habe viele Informationen überprüft und festgestellt, dass ich eine Konfiguration hinzufügen muss, die das Hinzufügen von Authentifizierungsinformationen zum Frontend ermöglicht

axios.defaults.withCredentials=true;

Das Backend muss auch eine entsprechende Konfiguration „allowCredentials(true)“ vornehmen;

@Bean
public WebMvcConfigurer corsConfigurer() {
 return new WebMvcConfigurerAdapter() {
  @Override
  public void addCorsMappings(CorsRegistry registry) {
   registry.addMapping("/**")
     .allowedHeaders("*")
     .allowedMethods("*")
     .allowedOrigins("*").allowCredentials(true);
  }
 };
}

Nach dem Hinzufügen dieser Konfiguration re - Führen Sie den Vorgang aus und stellen Sie nach der Anmeldung fest, dass er normal funktioniert. Springen Sie zum System und die Seitendaten werden normal angezeigt.

Gerade als ich dachte, ich wäre fertig, klickte ich plötzlich auf eine Seite und die Daten konnten nicht normal angezeigt werden. Ich war so verwirrt, dass ich schnell F12 fand und eine Anfragemethode fand, die ich noch nie zuvor gesehen hatte Anfrage Es stellt sich heraus, dass diese Anfragemethode offensichtlich POST ist. Warum wurde sie zu OPTIONS? Also bestellte ich mehrere andere POST-Anfragen und stellte fest, dass sie alle zu OPTIONS-Anfragen wurden. Ich war verwirrt und überprüfte schnell die Informationen von OPTIONS-Anfragen. Im Internet hieß es, dass OPTIONS-Anfragen „Vorabprüfungsanfragen“ heißen Nachdem die Anforderung ausgeführt wurde, initiiert der Browser zunächst eine Vorabprüfungsanforderung. Erst nachdem die Vorabprüfungsanforderung erfolgreich war, kann die formelle Anforderung ausgeführt werden. Nachdem ich es gelesen hatte, wurde mir plötzlich klar, dass OPTIONS abgefangen wurde, sodass ich meine POST-Anfrage nicht mehr ausführen konnte. Dann ließ ich die Vorabprüfungsanfrage einfach passieren. Fügen Sie dieses Urteil einfach dem Interceptor hinzu

//option预检查,直接通过请求
if ("OPTIONS".equals(request.getMethod())){
 return true;
}

Wenn der Interceptor auf diese Weise feststellt, dass es sich bei der Anfrage um eine Vorabprüfungsanforderung handelt, leitet er sie direkt weiter Sie können den nächsten Schritt POST-Anfrage ausführen.

Ich habe das Obige für Sie zusammengestellt und hoffe, dass es Ihnen in Zukunft hilfreich sein wird.

Verwandte Artikel:

Lösung des Problems, dass Webpack nicht auf 127.0.0.1 zugreifen kann

Verwendung von Async in Node.js und Wartefunktion

Übergabe der Vorlage an die Komponente in Angular

Das obige ist der detaillierte Inhalt vonWie vue+springboot domänenübergreifende Single-Sign-On-Probleme implementiert (ausführliches Tutorial). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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