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 공식 웹사이트에서 콜백 도메인 이름을 구성할 때 http 또는 https 프로토콜은 필요하지 않습니다. http://baidu.com과 같은 도메인만 작성하면 됩니다. baidu.com을 입력하면 됩니다. baidu.com/auth/wechat과 같은 프로젝트 아래의 컨트롤러 메소드로 이동하려면 구성할 때 baidu.com만 구성하면 되며 지정할 필요가 없습니다. auth/wechat, 코드에서 콜백 주소를 구성할 때 다음 주소를 작성할 수 있습니다. 코드는 https://baidu.com/auth/wechat
2로 구성해야 합니다. , QR 코드가 표시되지 않는 상황이 발생합니다. 이는 코드의 콜백 주소 때문입니다. 위의 코드에서 구성하면 문제가 없습니다.
위 내용은 Springboot가 웹사이트에 대한 제3자 로그인을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!