Springboot が Web サイトへのサードパーティ ログインを実装する方法

王林
リリース: 2023-05-16 18:35:07
転載
813 人が閲覧しました

ステップ 1: AuthService、WeChatAuthService を継承するインターフェイスを次のように作成します

public interface WeChatAuthService extends AuthService {
  public JSONObject getUserInfo(String accessToken, String openId);
}
ログイン後にコピー

ステップ 2: WeChatService の具体的な実装は次のとおりです

@Service
public class WeChatAuthServiceImpl extends DefaultAuthServiceImpl implements WeChatAuthService {

  private Logger logger = LoggerFactory.getLogger(WeChatAuthServiceImpl.class);

//请求此地址即跳转到二维码登录界面
  private static final String AUTHORIZATION_URL =
      "https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";

  // 获取用户 openid 和access——toke 的 URL
  private static final String ACCESSTOKE_OPENID_URL =
      "https://api.weixin.qq.com/sns/oauth3/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";

  private static final String REFRESH_TOKEN_URL =
      "https://api.weixin.qq.com/sns/oauth3/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s";

  private static final String USER_INFO_URL =
      "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";

  private static final String APP_ID="xxxxxx";
  private static final String APP_SECRET="xxxxxx";
  private static final String SCOPE = "snsapi_login";

  private String callbackUrl = "https://www.xxx.cn/auth/wechat"; //回调域名

  @Override
  public String getAuthorizationUrl() throws UnsupportedEncodingException {
    callbackUrl = URLEncoder.encode(callbackUrl,"utf-8");
    String url = String.format(AUTHORIZATION_URL,APP_ID,callbackUrl,SCOPE,System.currentTimeMillis());
    return url;
  }


  @Override
  public String getAccessToken(String code) {
    String url = String.format(ACCESSTOKE_OPENID_URL,APP_ID,APP_SECRET,code);

    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
    URI uri = builder.build().encode().toUri();

    String resp = getRestTemplate().getForObject(uri, String.class);
    logger.error("getAccessToken resp = "+resp);
    if(resp.contains("openid")){
      JSONObject jsonObject = JSONObject.parseObject(resp);
      String access_token = jsonObject.getString("access_token");
      String openId = jsonObject.getString("openid");;

      JSONObject res = new JSONObject();
      res.put("access_token",access_token);
      res.put("openId",openId);
      res.put("refresh_token",jsonObject.getString("refresh_token"));

      return res.toJSONString();
    }else{
      throw new ServiceException("获取token失败,msg = "+resp);
    }
  }

  //微信接口中,token和openId是一起返回,故此方法不需实现
  @Override
  public String getOpenId(String accessToken) {
    return null;
  }

  @Override
  public JSONObject getUserInfo(String accessToken, String openId){
    String url = String.format(USER_INFO_URL, accessToken, openId);
    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
    URI uri = builder.build().encode().toUri();

    String resp = getRestTemplate().getForObject(uri, String.class);
    logger.error("getUserInfo resp = "+resp);
    if(resp.contains("errcode")){
      throw new ServiceException("获取用户信息错误,msg = "+resp);
    }else{
      JSONObject data =JSONObject.parseObject(resp);

      JSONObject result = new JSONObject();
      result.put("id",data.getString("unionid"));
      result.put("nickName",data.getString("nickname"));
      result.put("avatar",data.getString("headimgurl"));

      return result;
    }
  }

  //微信的token只有2小时的有效期,过时需要重新获取,所以官方提供了
  //根据refresh_token 刷新获取token的方法,本项目仅仅是获取用户
  //信息,并将信息存入库,所以两个小时也已经足够了
  @Override
  public String refreshToken(String refresh_token) {

    String url = String.format(REFRESH_TOKEN_URL,APP_ID,refresh_token);

    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
    URI uri = builder.build().encode().toUri();

    ResponseEntity<JSONObject> resp = getRestTemplate().getForEntity(uri,JSONObject.class);
    JSONObject jsonObject = resp.getBody();

    String access_token = jsonObject.getString("access_token");
    return access_token;
  }
}
ログイン後にコピー

ステップ 3:

コントローラーで呼び出されるコードは次のとおりです:

@RequestMapping(value = "/wxLoginPage",method = RequestMethod.GET)
  public JSONObject wxLoginPage() throws Exception {
    String uri = weChatAuthService.getAuthorizationUrl();
    return loginPage(uri);
  }

  @RequestMapping(value = "/wechat")
  public void callback(String code,HttpServletRequest request,HttpServletResponse response) throws Exception {
    String result = weChatAuthService.getAccessToken(code);
    JSONObject jsonObject = JSONObject.parseObject(result);

    String access_token = jsonObject.getString("access_token");
    String openId = jsonObject.getString("openId");
//    String refresh_token = jsonObject.getString("refresh_token");

    // 保存 access_token 到 cookie,两小时过期
    Cookie accessTokencookie = new Cookie("accessToken", access_token);
    accessTokencookie.setMaxAge(60 *2);
    response.addCookie(accessTokencookie);

    Cookie openIdCookie = new Cookie("openId", openId);
    openIdCookie.setMaxAge(60 *2);
    response.addCookie(openIdCookie);

    //根据openId判断用户是否已经登陆过
    KmsUser user = userService.getUserByCondition(openId);

    if (user == null) {
      response.sendRedirect(request.getContextPath() + "/student/html/index.min.html#/bind?type="+Constants.LOGIN_TYPE_WECHAT);
    } else {
      //如果用户已存在,则直接登录
      response.sendRedirect(request.getContextPath() + "/student/html/index.min.html#/app/home?open_id=" + openId);
    }
  }
ログイン後にコピー

ステップ 4:

フロントエンド js では、まず auth/wxLoginPage にリクエストして認可アドレスを取得し、ユーザーが認可すると /auth/wechat がコールバックされるので、このメソッド内で論理的な処理を行うだけです。

遭遇した落とし穴:

1. WeChat 公式 Web サイトでコールバック ドメイン名を構成する場合、http または https プロトコルは必要なく、ドメインを記述するだけで済みます。例: http://baidu.com の場合は、baidu.com と入力するだけで済みます。baidu.com/auth/wechat など、プロジェクト配下のコントローラーのメソッドにジャンプしたい場合は、それを設定するだけです。 baidu.com を設定する必要がありますが、後続の auth/wechat を指定する必要はありません。コード内でコールバック アドレスを設定するときに後続のアドレスを記述するだけで済みます。コードは https://baidu として設定する必要があります。 com/auth/wechat
2. 認証 QR コード インターフェイスにジャンプすると、コード内のコールバック アドレスが原因で QR コードが表示されない状況が発生することがあります。上記のコードは問題ありません

以上がSpringboot が Web サイトへのサードパーティ ログインを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:yisu.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート