この記事では、vue+springboot のフロントエンドとバックエンドを分離することによる、シングル サインオンのクロスドメイン問題の解決策を主に紹介します。必要な友人は参照してください
現在、バックに取り組んでいます。 -エンド管理システム。フロントエンドは人気のある vue.js を使用します。バックグラウンドは springboot に基づいています。バックエンドシステムにはログイン機能がありませんが、統一ログインが必要なため、ログイン認証には.netプロジェクトチームの認証システムを利用しています。つまり、シングル サインオンを行うということです。シングル サインオンが何なのかわからない学生には、万能の Du Niang にアクセスすることをお勧めします。
最初にこの要件を受け取ったとき、私は軽蔑しながらこう思いました。ログインするだけでは重要ではありません。しかし、開発プロセスは私を激しく叩きました(熱い平手打ち)。 。 。 , したがって、将来そのような落とし穴に足を踏み込まないように、今回はこの教訓をしっかりと記録する必要があります。
私が最初に直面した問題は、ブラウザ コンソールが CORS を直接報告することでした。私は、長年の開発経験を活かして、バックグラウンドでクロスドメイン構成を設定しました。コードは次のとおりです。
この設定では、すべてのマッピング、すべてのリクエスト ヘッダー、すべてのリクエスト メソッド、およびすべてのソースが許可されます。構成を変更した後、効果を確認するために思い切ってプロジェクトを再起動したところ、ブラウザー エラーの原因がクロスドメインであることがわかり、最初に のコードをアップロードしました。私のログインインターセプター
@Configuration public class CorsConfiguration { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedHeaders("*") .allowedMethods("*") .allowedOrigins("*"); } }; } }
その後、フロントエンド vue は
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; }
を使用してバックエンド ログイン インターフェイスを直接リクエストし、フロントエンドはシステムにアクセスし、シングル サインに直接ジャンプできます。 -ページ内。しかし、アカウントとパスワードを入力してクリックしてログインすると、システムに戻って、すべてのリクエスト データ インターフェイスに正常にアクセスできないことがわかりました。デバッグでは、すべてのリクエストにユーザー情報が含まれておらず、インターセプターによって認識されたことがわかりました。ログインしていないため、すべてのリクエストが通過できませんでした。
なぜ私は明らかにログインしているのに、インターセプターはユーザー情報をセッションに設定するのですか? なぜ Cookie が消えてしまうのでしょうか?再度リクエストを開始したところ、各リクエストの JsessionId が異なることがわかりました。多くの情報を確認したところ、フロントエンドに認証情報を追加できるように構成を追加する必要があることがわかりました
window.location.href=this.$api.config.baseUrl+"/system/user/login"
。バックエンドも対応する設定を行う必要がありますallowCredentials(true );
axios.defaults.withCredentials=true;
この設定を追加した後、操作プロセスを再実行したところ、ログイン後は通常どおりシステムにジャンプし、ページデータにジャンプできることがわかりましたも正常に表示されます。
終わったと思ったら、突然ページをクリックしてしまい、データが正常に表示されなくなり、慌ててF12を押すと、OPTIONSリクエストという、見たことのないリクエスト方法が見つかりました。このリクエストメソッドは明らかに POST でしたが、なぜ OPTIONS になったのでしょうか?そこで、他の POST リクエストをいくつか注文しましたが、それらはすべて OPTIONS リクエストになっていることがわかり、混乱してすぐに OPTIONS リクエストの情報を確認しました。OPTIONS リクエストは正式には「事前チェック リクエスト」と呼ばれているとのことです。リクエストが実行される前に、ブラウザはまず事前チェック リクエストを開始します。事前チェック リクエストが通過した後でのみ、正式なリクエストを実行できます。これを読んだ後、OPTIONS がインターセプトされたため、POST リクエストを実行できなくなったことに突然気づきました。その後、事前チェックリクエストを通過させました。この判断をインターセプターに追加するだけです
@Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedHeaders("*") .allowedMethods("*") .allowedOrigins("*").allowCredentials(true); } }; }
このように、インターセプターがリクエストが事前チェックリクエストであると判断した場合はそのままパスし、次のPOSTリクエストを実行することができます。
上記は私があなたのためにまとめたものです。
関連記事:
webpackが127.0.0.1にアクセスできない問題を解決する以上がvue+springboot によるシングル サインオンのクロスドメイン問題の実装方法 (詳細なチュートリアル)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。