300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 微信登录(授权登录 扫码登录 静默登录)简述

微信登录(授权登录 扫码登录 静默登录)简述

时间:2019-08-15 07:40:23

相关推荐

微信登录(授权登录 扫码登录 静默登录)简述

大家好,今天聊聊微信登录

微信登录我写过的有三种登录方法(授权登录、静默登录、扫码登录)这里说一下我的看法(个人观点,欢迎拍砖)。

1、授权登录需要拉起需要用户确认的授权页(`・ω・´)

有些人可能会不喜欢,例如我老板(T_T),此方式可以获取比较多的信息,例如头像、昵称、openid、unionid、是否关注公众号等信息

个人认为此种授权方式比较适合纯在微信端运营的网站,如果不考虑脱离微信端的话。

2、静默登录,这个当前环境下很流行,用appid去获取code然后获取用户的openid,拿到openid之后就可以进行自己业务处理了,从体验上来说用户无感,没有上面那个授权页,个人认为此种授权方式比较适合较为独立或者正在考虑脱离微信的网站,

3、扫码登录,此种方式一般适用于电商网站的PC登录,如下图

好啦,开始介绍开发流程。

1、授权登录:

a)、首先需要在公众号取得相应的获取用户基本信息的权限。推荐适用拦截器的方式拦截部分需要授权的功能,例如钱包、个人中心等,对于网站介绍,或者一些推广页、首页这些不需要授权可以提升一下用户体验,虽然从开发的角度看意义不大,拦截代码如下

package com.xxx.filter;import com.xxx.util.CookieUtil;import com.xxx.util.IPUtil;import mons.lang.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.servlet.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;public class WeChatUserFilter implements Filter {protected static final Logger LOG = LoggerFactory.getLogger(WeChatUserFilter.class);@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest _request, ServletResponse _response, FilterChain chain)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) _request;HttpServletResponse response = (HttpServletResponse) _response;// 获取当前访问路径String path = request.getRequestURI().toString();// 拦截地址配置String[] filterUrls = { "/home", "/XXXX/XXX", "/XXX/XXXX" };for (String url : filterUrls) {if (path.contains(url)) {// 拦截LOG.info("拦截的地址是:" + path + ",ip:" + IPUtil.getIpAddr(request));String openid = CookieUtil.getCookieValue(request, "openid");if (StringUtils.isNotBlank(openid)) {chain.doFilter(_request, _response);return;}if (StringUtils.isNotBlank(request.getQueryString())) {path += "?" + request.getQueryString();}response.sendRedirect(response.encodeURL("/user/login?u=" + response.encodeURL(path)));return;}}chain.doFilter(_request, _response);}@Overridepublic void init(FilterConfig arg0) throws ServletException {// TODO Auto-generated method stub}}

b)、如果用户没有进行过授权则会跳转到/user/login中进行登录,完整的登录代码如下

@RestController@RequestMapping(value = "user")public class LoginController {protected static final Logger LOG = LoggerFactory.getLogger(LoginController.class);// 公众号APPIDpublic static final String WX_APPID = "XXXXXXXXXXXX";// 公众号SECRETpublic static final String WX_APP_SECRET = "XXXXXXXXXXXX";@RequestMapping(value = "login", method = RequestMethod.GET)public void toLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {// 获取cookie中的openidString openid = CookieUtil.getCookieValue(request, "openid");String unionid = CookieUtil.getCookieValue(request, "unionid");// 定义微信授权之后的跳转地址命名方式为(http://你的网址+/user/login?u=)String reUrl = "";// 获取需要跳转的urlString u = request.getParameter("u");LOG.error("需要跳转的url为:", u);// 判断如果openid不存在,则获取code// 如果拦截到的跳转的地址为空则给个默认值if (StringUtils.isBlank(u)) {u = "/indexController/index";}if (StringUtils.isBlank(openid) || StringUtils.isBlank(unionid)) {// 获取codeString code = request.getParameter("code");LOG.error("code:", code);if (StringUtils.isBlank(code)) {// 跳转到微信端获取codeString redrictUrl = response.encodeURL(reUrl + response.encodeURL(u));String url = "https://open./connect/oauth2/authorize?appid=" + WX_APPID + "&redirect_uri="+ redrictUrl + "&response_type=code&scope=snsapi_userinfo&state=0#wechat_redirect";try {response.sendRedirect(url);} catch (IOException e) {// logger.error("url:重定向错误");}return;} else {// 获取用户信息JSONObject object = getSnsapiUserinfo(request, code);if (object != null) {String user_unionid = object.getString("unionid");String user_openid = object.getString("openid");if (StringUtils.isBlank(user_unionid) || StringUtils.isBlank(user_openid)) {return;}String headimgurl = object.getString("headimgurl");String nickname = EmojiFilter.filterEmoji(object.getString("nickname"));}}}// 返回客户访问页面try {response.sendRedirect(u);} catch (IOException e) {// logger.error("url:重定向错误");}}public static JSONObject getSnsapiUserinfo(HttpServletRequest request, String code)throws mons.httpclient.HttpException {JSONObject wxuser;String t_url = "https://api./sns/oauth2/access_token?appid=" + WX_APPID + "&secret="+ WX_APP_SECRET + "&code=" + code + "&grant_type=authorization_code";Proxy httproxy = new Proxy();final String result = httproxy.get(t_url, null);LOG.info("sns/oauth2/access_token:" + result);JSONObject obj = JSON.parseObject(result);String openid = obj.getString("openid");// 判断用户是否存在String t_access_token = obj.getString("access_token");String t_url_2 = "https://api./sns/userinfo?access_token=" + t_access_token + "&openid=" + openid;final String res2 = httproxy.get(t_url_2, null);wxuser = JSON.parseObject(res2);LOG.info("网页授权获取用户基本信息:" + wxuser.toString());return wxuser;}}

2、静默登录 静默登录只需在授权登录的基础之上更改scope参数的值即可 如下

String url = "https://open./connect/oauth2/authorize?appid=" + WX_APPID + "&redirect_uri="+ redrictUrl + "&response_type=code&scope=snsapi_base&state=0#wechat_redirect";

3、扫码登录就简单很多了

只需拉起微信扫码页然后设置扫码成功之后的回调方法即可,具体如下:

a)、拉起微信扫码登录页

String WX_SCAN_CODE_URL = "https://open./connect/qrconnect?appid={APPID}&redirect_uri={REUTL}&response_type=code&scope=snsapi_login&state={STATE}#wechat_redirect";// 千万要记住,这个是微信开放平台的APPIDString WX_PLATFROM_APPID = "XXXXXX";// 你的回调地址String scanReUrl = "http://你的网址/user/wxLoginCallback";/*** 微信扫码登陆* * @param request* @param response*/@RequestMapping(value = "weixinScanLogin", method = RequestMethod.GET)public void weixinRetrun(HttpServletRequest request, HttpServletResponse response) throws Exception {// 获取回调url(非必填,只是附带上你扫码之前要进入的网址,具体看业务是否需要)String url = request.getParameter("reurl");// 拼接扫码登录urlString wxLoginurl = WX_SCAN_CODE_URL;wxLoginurl = wxLoginurl.replace("{APPID}", WX_PLATFROM_APPID).replace("{REUTL}", scanReUrl).replace("{STATE}",url);wxLoginurl = response.encodeURL(wxLoginurl);response.sendRedirect(wxLoginurl);}

b)、微信扫码登录的回调地址

// 千万要记住,这个是微信开放平台的APPIDString WX_PLATFROM_APPID = "XXXXXXXXX";// 千万要记住,这个是微信开放平台的APPSECRETString WX_PLATFORM_APPSECRET = "XXXXXXXXXX";// 拉起微信扫码页地址String WX_SCAN_URL = "https://api./sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";// 微信扫码之后获取用户基本信息的地址String WX_SCAN_GET_USER_INFO = "https://api./sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";/*** 微信扫码登录回调* * @param request* @param response* @return* @throws Exception*/@RequestMapping(value = "wxLoginCallback", method = RequestMethod.GET)public void loginCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {String code = request.getParameter("code");if (code == null) {// 用户禁止授权}String url = WX_SCAN_URL.replace("APPID", WX_PLATFROM_APPID).replace("SECRET", WX_PLATFORM_APPSECRET).replaceAll("CODE", code);url = response.encodeURL(url);try {String result = HttpClientUtils.get(url, null);Map<String, Object> resultMap = JsonHelper.toMap(result);String unionid = (String) resultMap.get("unionid");String access_token = (String) resultMap.get("access_token");String openid = (String) resultMap.get("openid");// 这里可以根据获取的信息去库中判断是否存在库中 如果不存在执行以下方法// 如果该用户不存在数据库中// 获取用户信息url = ConstantHelper.WX_SCAN_GET_USER_INFO.replace("ACCESS_TOKEN", access_token).replace("OPENID", openid);url = response.encodeURL(url);String userResult = HttpClientUtils.get(url, null);Map<String, Object> userResultMap = JsonHelper.toMap(userResult);// 注册一个用户System.out.println("扫码登录返回值******************:" + userResult);String headimgurl = (String) userResultMap.get("headimgurl");// 处理微信名特殊符号问题 过滤图标String nickname = (String) userResultMap.get("nickname");// 把用户信息存入session中} catch (Exception e) {e.printStackTrace();}// 返回地址try {String newUrl = request.getParameter("state");response.sendRedirect(newUrl);} catch (IOException e) {// logger.error("url:重定向错误");}}

下面附上几个工具类

public class Proxy {// constpublic final static int DEFAULT_CONNECT_TIMEOUT = 15000 * 2;public final static int DEFAULT_SO_TIMEOUT = 30000 * 2;public final static int DEFAULT_BUFFER_SIZE = 256;public final static int DEFAULT_MAX_CONNECTIONS = 200 * 2;private final static String CS_PREFIX = "charset=";private final static int CS_PREFIX_LEN = CS_PREFIX.length();// 数据编码格式private final String encoding;// clientprivate final HttpClient client;// bufferprivate final int bufferSize;public Proxy() {this("UTF-8", DEFAULT_CONNECT_TIMEOUT, DEFAULT_SO_TIMEOUT, DEFAULT_BUFFER_SIZE, DEFAULT_MAX_CONNECTIONS);}public Proxy(final String encoding) {this(encoding, DEFAULT_CONNECT_TIMEOUT, DEFAULT_SO_TIMEOUT, DEFAULT_BUFFER_SIZE, DEFAULT_MAX_CONNECTIONS);}public Proxy(final int bufferSize) {this("UTF-8", DEFAULT_CONNECT_TIMEOUT, DEFAULT_SO_TIMEOUT, bufferSize, DEFAULT_MAX_CONNECTIONS);}public Proxy(final String encoding, final int connectTimeout, final int soTimeout) {this(encoding, connectTimeout, soTimeout, DEFAULT_BUFFER_SIZE, DEFAULT_MAX_CONNECTIONS);}public Proxy(final String encoding, final int connectTimeout, final int soTimeout, final int bufferSize) {this(encoding, connectTimeout, soTimeout, bufferSize, DEFAULT_MAX_CONNECTIONS);}public Proxy(final String encoding, final int connectTimeout, final int soTimeout, final int bufferSize, final int maxConnections) {this.encoding = encoding;// connect-parametersfinal HttpConnectionManagerParams mp = new HttpConnectionManagerParams();mp.setConnectionTimeout(connectTimeout);mp.setSoTimeout(soTimeout);mp.setStaleCheckingEnabled(true);mp.setTcpNoDelay(true);mp.setMaxTotalConnections(maxConnections);final HttpConnectionManager mgr = new SimpleHttpConnectionManager();mgr.setParams(mp);// client-initthis.client = new HttpClient(mgr);// client-parametersfinal HttpClientParams cparams = new HttpClientParams();// 设置httpClient的连接超时,对连接管理器设置的连接超时是无用的cparams.setConnectionManagerTimeout(connectTimeout);this.client.setParams(cparams);this.bufferSize = bufferSize;}public HttpClient getClient() {return client;}public String getEncoding() {return encoding;}public String post(final String url, final Map<String, String> headers, final Map<String, String> data, final String encoding) throws HttpException {// post方式final PostMethod post = new PostMethod(url);// headerssetHeaders(post, headers);// contentif (data != null) {Set<Map.Entry<String, String>> postset = data.entrySet();final NameValuePair[] params = new NameValuePair[postset.size()];int i = 0;for (Iterator<Map.Entry<String, String>> it = postset.iterator(); it.hasNext();) {Map.Entry<String, String> p = it.next();params[i++] = new NameValuePair(p.getKey(), p.getValue());}post.setRequestBody(params);}try {return (execute(post, encoding));} finally {post.releaseConnection();}}public String post(final String url, final Map<String, String> data, final String encoding) throws HttpException {return post(url, null, data, encoding);}@SuppressWarnings("deprecation")public String post(final String url, final Map<String, String> headers, final String data, final String encoding) throws HttpException {// post方式final PostMethod post = new PostMethod(url);// headerssetHeaders(post, headers);// contentif (data != null) {try {final InputStream bin = new ByteArrayInputStream(data.getBytes(this.encoding));post.setRequestBody(bin);} catch (final UnsupportedEncodingException e) {}}try {return (execute(post, encoding));} finally {post.releaseConnection();}}public String post(final String url, final String data, final String encoding) throws HttpException {// post方式return post(url, null, data, encoding);}public String get(final String url, final Map<String, String> headers) throws HttpException {// get方式final GetMethod get = new GetMethod(url);try {// headerssetHeaders(get, headers);return (execute(get, encoding));} finally {get.releaseConnection();}}private final HttpMethod setHeaders(final HttpMethod method, final Map<String, String> headers) {if (headers != null) {final Set<Map.Entry<String, String>> headset = headers.entrySet();for (Iterator<Map.Entry<String, String>> it = headset.iterator(); it.hasNext();) {Map.Entry<String, String> header = it.next();method.setRequestHeader(header.getKey(), header.getValue());}}return method;}private String execute(final HttpMethod method, final String encoding) throws HttpException {InputStream in = null;BufferedReader reader = null;try {client.executeMethod(method);// get-encodingString encode = encoding;final Header ctypeh = method.getResponseHeader("Content-Type");if (ctypeh != null) {final String cv = ctypeh.getValue();final String ctype;if (cv == null) {ctype = null;} else {ctype = cv.toLowerCase(Locale.ENGLISH);}final int i;if (ctype != null && (i = ctype.indexOf(CS_PREFIX)) != -1) {encode = ctype.substring(i + CS_PREFIX_LEN).trim();// test encodingtry {"a".getBytes(encode);} catch (UnsupportedEncodingException e) {encode = encoding;}//}}//if (encode == null) {return (method.getResponseBodyAsString());}in = method.getResponseBodyAsStream();reader = new BufferedReader(new InputStreamReader(in, encode), bufferSize);final StringBuffer sbuf = new StringBuffer(bufferSize >>> 1);for (String line = reader.readLine(); line != null; line = reader.readLine()) {sbuf.append(line).append("\r\n");}return (sbuf.toString());} catch (IOException e) {throw new HttpException(e.getMessage());} finally {if (reader != null) {try {reader.close();} catch (IOException e) {}}if (in != null) {try {in.close();} catch (IOException e) {}}}}}

下面这个工具类是去除微信名中的Emoji表情

public class EmojiFilter {/*** 检测是否有emoji字符* @param source* @return 一旦含有就抛出*/public static boolean containsEmoji(String source) {if (StringUtils.isBlank(source)) {return false;}int len = source.length();for (int i = 0; i < len; i++) {char codePoint = source.charAt(i);if (isEmojiCharacter(codePoint)) {//do nothing,判断到了这里表明,确认有表情字符return true;}}return false;}private static boolean isEmojiCharacter(char codePoint) {return (codePoint == 0x0) ||(codePoint == 0x9) ||(codePoint == 0xA) ||(codePoint == 0xD) ||((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||((codePoint >= 0x10000) && (codePoint <= 0x10FFFF));}/*** 过滤emoji 或者 其他非文字类型的字符* @param source* @return*/public static String filterEmoji(String source) {if (!containsEmoji(source)) {return source;//如果不包含,直接返回}//到这里铁定包含StringBuilder buf = null;int len = source.length();for (int i = 0; i < len; i++) {char codePoint = source.charAt(i);if (isEmojiCharacter(codePoint)) {if (buf == null) {buf = new StringBuilder(source.length());}buf.append(codePoint);} else {}}if (buf == null) {return source;//如果没有找到 emoji表情,则返回源字符串} else {if (buf.length() == len) {//这里的意义在于尽可能少的toString,因为会重新生成字符串buf = null;return source;} else {return buf.toString();}}}}

如果有什么问题咱们可以讨论一下(~ ̄▽ ̄)~

转载需注明出处,不然你会尝到正义的小拳拳

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。