微信登录的优势
目前微信用户数量巨大,用户更希望通过更快更便捷的方式进行登录,而不是传统的账号密码登录。
springboot
接入微信登陆
准备工作
网站应用微信登录是基于OAuth2.0协议标准构建的微信OAuth2.0授权登录系统。 在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的网站应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程。
说白了就是需要一个AppID和对应的Appsecret
传送门:微信开放平台 (qq.com)
登陆后选一个,这里是网站应用
顺便再把回调域改一下。
授权流程
那我们要做什么呢?
设置一个链接让用户跳转到微信登录扫码界面,然后用户点确认后会带上
code
和state
重定向到我们设置的回调域,这是我们带上code访问微信获得用户的一些基本信息和access_token
refresh_token
,有了token我们就可以获取用户具体的信息了。这时候我们再设置session就可以让用户登录成功了。
-
打开链接
设置一个链接,格式如下:
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
0. 添加回调域网址接受回调信息
在用户授权之后,将会重定向到回调域,redirect_uri?code=CODE&state=STATE这时我们就获取了code,随后访问链接获取 access_token`https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code`
正确的返回:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
参数 | 说明 |
---|---|
access_token | 接口调用凭证(我们需要的) |
expires_in | access_token接口调用凭证超时时间,单位(秒),一般是两小时 |
refresh_token | 用户刷新access_token |
openid | 授权用户唯一标识,对于当前appid是唯一的 |
scope | 用户授权的作用域,使用逗号(,)分隔 |
unionid | 当且仅当该网站应用已获得该用户的userinfo授权时,才会出现该字段。 |
-
获取用户详细信息
继续访问https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID就可以获取用户的详细信息了
实际操作
1. appId和appSecret的配置
在application.yml的配置:
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@Data
@ConfigurationProperties(prefix = "wx")
public class WXConfig {private String appId;private String appSecret;
}
2. 设置网址
3. 设置回调域
导包
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.78</version>
</dependency>
工具类
public class CommonUtil {private static final int BUFFER_SIZE = 1024 * 8;public static String getBody(InputStream inputStream) throws IOException {Reader reader = new BufferedReader(new InputStreamReader(inputStream));StringWriter writer = new StringWriter();int read;char[] buf = new char[BUFFER_SIZE];while ((read = reader.read(buf)) != -1) {writer.write(buf, 0, read);}return writer.getBuffer().toString();}
}
回调域逻辑
@Slf4j
@Controller
public class WXController {@Autowiredprivate WXConfig wxConfig;
@ResponseBody@RequestMapping("/wx/login")public String login(HttpServletRequest request) throws IOException {String code = request.getParameter("code");String state = request.getParameter("state");if (code == null){log.error("用户取消登录");}log.info("code = {}", code);CloseableHttpClient httpClient = HttpClientBuilder.create().build();String url = "https://api.weixin.qq.com/sns/oauth2/access_token" +"?appid=" + wxConfig.getAppId() +"&secret=" + wxConfig.getAppSecret() +"&code=" + code +"&grant_type=authorization_code";HttpGet httpGet = new HttpGet(url);CloseableHttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();String body = CommonUtil.getBody(entity.getContent());log.info(body);response.close();
JSONObject bodyJson = JSON.parseObject(body);// 这里已经获取了用户的部分信息,可以在数据库中查询,如果已经记录过了,就没有必要进入后面的步骤了String accessToken = bodyJson.getString("access_token");String openId = bodyJson.getString("openId");
url = "https://api.weixin.qq.com/sns/userinfo" +"?access_token=" + accessToken +"&openid=" + openId;httpGet = new HttpGet(url);response = httpClient.execute(httpGet);body = CommonUtil.getBody(response.getEntity().getContent());bodyJson = JSON.parseObject(body);// 获取了用户信息后进行存储log.info("the info of user is {}", bodyJson);response.close();// 登录成功,设置sessionrequest.getSession().setAttribute("unionId", bodyJson.getString("union_id"));return "登录成功";}
}
\