Maison  >  Article  >  interface Web  >  Comment vue+springboot implémente les problèmes inter-domaines d'authentification unique (tutoriel détaillé)

Comment vue+springboot implémente les problèmes inter-domaines d'authentification unique (tutoriel détaillé)

亚连
亚连original
2018-06-08 18:19:523249parcourir

Cet article présente principalement la solution au problème inter-domaines de l'authentification unique via la séparation du front-end et du back-end de vue+springboot. Les amis dans le besoin peuvent s'y référer

Je le suis. travaille actuellement sur un système de gestion back-end. Le front-end utilise le populaire vue.js, le backend est basé sur springboot. Étant donné que le système backend n'a pas de fonction de connexion, mais que l'entreprise nécessite une connexion unifiée, l'authentification de connexion utilise le système d'authentification de l'équipe du projet .net. Cela signifie faire de l'authentification unique. Quant aux étudiants qui ne savent pas ce qu'est l'authentification unique, je vous suggère d'aller au Du Niang polyvalent.

Quand j'ai reçu cette exigence pour la première fois, j'ai pensé avec dédain : le simple fait de se connecter n'est pas important. Cependant, le processus de développement m'a durement giflé (une gifle chaude). . . , je dois donc bien enregistrer cette leçon cette fois pour éviter de tomber dans de tels pièges à l'avenir.

Le premier problème que j'ai rencontré était inter-domaine. La console du navigateur rapportait directement CORS. Grâce à mes nombreuses années d'expérience en développement, j'ai configuré de manière décisive la configuration inter-domaine en arrière-plan. 🎜>

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

Cette configuration autorise tous les mappages, tous les en-têtes de requêtes, toutes les méthodes de requête et toutes les sources. Après avoir modifié la configuration, j'ai redémarré le projet de manière décisive pour voir l'effet. J'ai constaté qu'il n'y avait aucun moyen de rediriger vers la page de connexion unique. Voyant que l'erreur du navigateur était causée par un interdomaine, j'ai d'abord téléchargé le code de. mon intercepteur de connexion

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;
}

Plus tard, la vue frontale demande l'interface de connexion back-end directement en utilisant

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

Une fois que le front-end a accédé au système, vous pouvez accéder directement à la page d'authentification unique. Mais lorsque j'ai entré le compte et le mot de passe et cliqué pour me connecter, je suis revenu au système et j'ai constaté que toutes les interfaces de données de demande n'étaient pas accessibles normalement. Debug a constaté que toutes les demandes ne contenaient pas d'informations utilisateur et étaient reconnues par l'intercepteur comme étant. pas connecté, donc toutes les demandes n’ont pas pu être acceptées.

Pourquoi, même si je suis connecté, l'intercepteur définit également les informations utilisateur sur la session ? Pourquoi les cookies ont-ils disparu ? J'ai réitéré la demande et j'ai constaté que le JsessionId de chaque demande était différent. J'ai vérifié beaucoup d'informations et j'ai découvert que je devais ajouter une configuration permettant d'ajouter des informations d'authentification au front-end

axios.defaults.withCredentials=true;

L'arrière-plan doit également effectuer une configuration correspondanteallowCredentials(true);

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

Après l'ajout cette configuration, réexécutez le processus d'opération et constatez qu'après m'être connecté, je peux accéder au système normalement et les données de la page s'affichent également normalement.

Juste au moment où je pensais avoir terminé, j'ai soudainement cliqué sur une page et les données ne pouvaient pas être affichées normalement. J'étais tellement confus que j'ai rapidement F12 et j'ai trouvé une méthode de requête que je n'avais jamais vue auparavant, les OPTIONS. request. Il s'avère que cette méthode de requête est évidemment POST, pourquoi est-elle devenue OPTIONS ? J'ai donc commandé plusieurs autres requêtes POST et j'ai découvert qu'elles se sont toutes transformées en requêtes OPTIONS. J'étais confus et j'ai rapidement vérifié les informations des requêtes OPTIONS. Internet a dit que les requêtes OPTIONS sont appelées "demandes de pré-vérification", ce qui signifie dans votre Avant formel. la demande est exécutée, le navigateur lancera d'abord une demande de pré-vérification. Ce n'est qu'une fois la demande de pré-vérification réussie que la demande formelle pourra être exécutée. Après l'avoir lu, j'ai soudain réalisé que OPTIONS avait été interceptée, je ne pouvais donc plus exécuter ma requête POST. Ensuite, j'ai simplement laissé passer la requête de pré-vérification. Ajoutez simplement ce jugement à l'intercepteur

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

De cette façon, si l'intercepteur constate que la demande est une demande de pré-vérification, il la transmettra directement et la connexion peut être exécutée en bas de la requête POST.

Ce qui précède est ce que j'ai compilé pour vous. J'espère que cela vous sera utile à l'avenir.

Articles connexes :

Résolution du problème selon lequel Webpack ne peut pas accéder à 127.0.0.1


Utilisation des fonctions Async et Await


Passage du modèle au composant dans Angular


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn