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("*"); } }; } }
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; }
window.location.href=this.$api.config.baseUrl+"/system/user/login"
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.1Utilisation des fonctions Async et Await Passage du modèle au composant dans AngularCe 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!