首先因为微信的接口都是https的,用HttpClient实现的话因为不清楚是否支持https,所以计划用ajax在客户端完成认证。不过这个绝对是一个十分愚蠢的想法,因为ajax跨域是一个不可逾越的障碍,只不过开始考虑的不周到,直到开始编码的时候才发现,而且还脑袋抽筋的想去解决它,真是耽误不少时间。
Ajax行不通以后,逼着使用HttpClient在后台实现了。还是担心HttpClient不支持https,所以在网上看了很久,大部分都是说要导入证书什么的,十分复杂。不过还是迫于无奈,只好找到HttpClient的文档直接就开始实验,发现原来这样访问https HttpClient 是完全支持的,和普通的http没有什么不同,之前的担心多余了,还浪费了好多时间去了解。
正式开始,其实微信的认证并不复杂。首先是要调用一个认证URL,引导用户授权(如果有必要),然后微信会回调指定的回调URL,成功的话返回code 参数,通过code就可以继续获取access_token 和 openid,如果之前用户授权的话,还可以获得用户昵称和地址等一些信息。
下面是组装认证URL和处理回调的代码,是从一个HttpServlet和 struts 代码里面直接裁出来的,就是这么个意思而已,编译不过的。
第一步,首先要构造一个认证URL,因为这个URL里面包含了回调URL和一个可以带过去的参数,所以一般还是要先自行组装一下。这里面有个地方要注意,state 参数协议里面说是仅支持字母和数字的,所以最好还是用来传一些简单的参数好了,有些人喜欢把一堆参数通过base64加密后放进state 里面传递,但我发现有些情况下还是容易出错,不要冒险的好。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { StringBuffer sbrCallbackUrl = new StringBuffer(); StringBuffer sbrWeiXinAuthUrl = new StringBuffer(); StringBuffer sbrParamer = new StringBuffer(); boolean boolFastAuth = false; int nServerPort = 0; int nPortalPageId = 0; String strToUser = request.getParameter("to_user"); if (null == strToUser || strToUser.trim().length()<=0) { log.error("WeixinWebAuth fail,need ToUser"); return; } //这个参数是用来指定是否需要引导用户到授权页面 String strFastAuth = request.getParameter("fast"); if (null != strFastAuth ) { log.info("Fast auth modle"); boolFastAuth = true; } String strAppId = "appid";//FIXME if (null == strAppId || strAppId.trim().length()<=0) { log.error("WeixinWebAuth fail,need appid"); return; } String strAppSecret = " AppSecret ";//FIXME if (null == strAppSecret || strAppSecret.trim().length()<=0) { log.error("WeixinWebAuth fail,need AppSecret"); return; } sbrParamer.append(PARAM); //FIXME sbrCallbackUrl.append(request.getScheme()+"://"); sbrCallbackUrl.append(request.getServerName()); sbrCallbackUrl.append(CALL_BACK_URL); //组装认证URL sbrWeiXinAuthUrl.append(WEIXIN_WEB_AUTH_URL); sbrWeiXinAuthUrl.append("?"); sbrWeiXinAuthUrl.append("appid=" + strAppId); sbrWeiXinAuthUrl.append("&"); sbrWeiXinAuthUrl.append("redirect_uri=" + java.net.URLEncoder.encode(sbrCallbackUrl.toString(),"UTF-8")); sbrWeiXinAuthUrl.append("&"); sbrWeiXinAuthUrl.append("response_type=code"); sbrWeiXinAuthUrl.append("&"); if (!boolFastAuth) { sbrWeiXinAuthUrl.append("scope=snsapi_userinfo"); } else { sbrWeiXinAuthUrl.append("scope=snsapi_base"); } sbrWeiXinAuthUrl.append("&"); sbrWeiXinAuthUrl.append("state="+sbrParamer); sbrWeiXinAuthUrl.append("#wechat_redirect"); log.info("Goto weixin auth path:" + sbrWeiXinAuthUrl); response.sendRedirect(sbrWeiXinAuthUrl.toString()); }
组装完地址,直接重定向过去。
第二步,就是要处理回调过来的信息。这个其实也比较简单。
import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONObject; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; public class WeixinWebAuthCallbackAction extends Action { private final String strAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token"; private final String strGetUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo"; @Override protected ActionForward executeAction(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception { response.setContentType("text/html"); response.setCharacterEncoding("UTF-8"); String strWeixinCallbackCode = null; String strParamers = null; log.info("微信web认证获取帐号开始"); strWeixinCallbackCode = request.getParameter("code"); log.info("return code:" + strWeixinCallbackCode); strParamers = request.getParameter("state"); log.info("return :" + strParamers); if (null == strWeixinCallbackCode || strWeixinCallbackCode.equals("authdeny") || null == strParamers || strParamers.isEmpty()) { log.info("用户拒绝授权"); request.setAttribute("errcode", 1); request.setAttribute("errmsg", "用户拒绝授权"); return mapping.findForward("fail"); } String strAccessToken = null; String strUserOpenId = null; String strNickName = ""; String strSex = "";//1 man;2 female;3 unknown; String address = ""; String strAppId = "AppId";//FIXME String strAppSecret = "AppSecret";//FIXME Map<String, String> mapAccessToken = getAccessTokenAndUid(strWeixinCallbackCode, strAppId, strAppSecret); if (null == mapAccessToken || null != mapAccessToken.get("errcode")) { log.info("获取访问token错误"); if (null != mapAccessToken) { request.setAttribute("errcode", mapAccessToken.get("errcode")); request.setAttribute("errmsg", mapAccessToken.get("errmsg")); } return mapping.findForward("fail"); } strAccessToken = mapAccessToken.get("access_token"); strUserOpenId = mapAccessToken.get("openid"); Map<String, String> mapUserInfo = getUserInfo(strAccessToken, strUserOpenId); if (null != mapUserInfo) { if(null != mapUserInfo.get("errcode")){ log.info("获取用户信息错误"); request.setAttribute("errcode", mapUserInfo.get("errcode")); request.setAttribute("errmsg", mapUserInfo.get("errmsg")); return mapping.findForward("fail"); } strNickName = mapUserInfo.get("nickname"); strSex = mapUserInfo.get("sex"); } log.info("weixin web auth,user:"+strNickName+" sex:"+strSex); return mapping.findForward("success"); } private Map<String , String> getAccessTokenAndUid(String strCode,String strAppId,String strAppSecret){ String responseDate = "" ; Map<String , String> token = null; PostMethod postMethod = new PostMethod(strAccessTokenUrl); postMethod.addParameter("appid", strAppId); postMethod.addParameter("secret",strAppSecret); postMethod.addParameter("code",strCode); postMethod.addParameter("grant_type","authorization_code"); HttpClient client = new HttpClient(); try { client.executeMethod(postMethod); responseDate = postMethod.getResponseBodyAsString(); } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } if(responseDate.trim().length()>0){ token = new HashMap<String, String>(); JSONObject jsonData = JSONObject.fromObject(responseDate); if (jsonData.has("errcode")) { log.error("Get access token fail,reason:" + jsonData.getString("errmsg")); token.put("errcode", jsonData.getString("errcode")); token.put("errmsg", jsonData.getString("errmsg")); return null; } log.info("Get access_token:"+jsonData.getString("access_token")+";openid:"+jsonData.getString("openid")); token.put("access_token", jsonData.getString("access_token")); token.put("openid", jsonData.getString("openid")); } return token; } private Map<String , String> getUserInfo(String strAccessToken,String strOpenId){ String responseDate = "" ; Map<String , String> token = null; PostMethod postMethod = new PostMethod(strGetUserInfoUrl); postMethod.addParameter("access_token", strAccessToken); postMethod.addParameter("openid",strOpenId); postMethod.addParameter("lang","zh_CN"); HttpClient client = new HttpClient(); try { client.executeMethod(postMethod); responseDate = postMethod.getResponseBodyAsString(); } catch (Exception e) { log.error(e.getMessage()); e.printStackTrace(); } if(responseDate.trim().length()>0){ token = new HashMap<String, String>(); JSONObject jsonData = JSONObject.fromObject(responseDate); if (jsonData.has("errcode")) { log.info("Get user info fail,reason:["+jsonData.getString("errcode")+ "]" + jsonData.getString("errmsg")); //这个是没用户授权,不能取用户信息的返回错误码,文档没提及,随时可能变的 if (48001 == jsonData.getLong("errcode")) { log.info("Can't get userinfo,but wo can continue."); return null; } token.put("errcode", jsonData.getString("errcode")); token.put("errmsg", jsonData.getString("errmsg")); return token; } if (!jsonData.has("openid") || !jsonData.has("nickname")) { log.info("No user info available"); return null; } log.info("weixin web auth,user:"+jsonData.getString("nickname")+" sex:"+jsonData.getString("sex") + " province:"+jsonData.getString("province")+" city:"+jsonData.getString("city") + " country:"+jsonData.getString("country")); token.put("openid", jsonData.getString("openid")); token.put("nickname", jsonData.getString("nickname")); token.put("sex", jsonData.getString("sex")); token.put("province", jsonData.getString("province")); token.put("city", jsonData.getString("city")); token.put("country", jsonData.getString("country")); } return token; } }
相关推荐
微信OAuth2.0网页授权接口的thinkphp实现版本,主要实现了oauth网页受权,以及部分其他接口。 使用方法 为什么用OAuth2.0受权? 通过OAuth2.0受权的网页将会获取到打开者的微信信息,甚至包括微信昵称、头像等有用...
微信OAuth2.0网页授权接口PHP版用法示例,测试前请先申请一个公众号供测试,微信提供测试用的公众账号,此帐号只能添加100个关注者且只有__已关注__的用户才可以进行OAuth2.0受权。 1.开通后将```appID```、```app...
总之,`php版微信授权登陆`结合微信OAuth2网页授权登录接口,为开发者提供了一种简单有效的用户认证方式,让网站或应用能够利用微信庞大的用户群体,提升用户体验和活跃度。在实际开发中,你需要根据自己的需求调整...
3、网页服务--》网页帐号--》修改--》授权回调页面域名: 882c783d.ngrok.io 该域名为ngrok域名 4、修改程序中 appID值 org.liufeng.course.servlet.OAuthServlet AdvancedUtil.getOauth2AccessToken() org.liufeng....
使用idea开发工具,基于springboot2.x、jwt鉴权、nginx集群,前后端分离的微信Oauth2.0一键登录和微信网页扫码支付测试开发demo
微信公众平台开发OAuth2.0网页授权认证
.NET Core 企业微信网页授权登录是指使用微信企业号的 OAuth2 授权机制来实现网页登录的功能。在这个过程中,需要获取企业的唯一标识 corpid 和访问密钥 secret,然后使用这两个参数来构造 OAuth2 授权链接,以便...
总的来说,Java微信开发API中的网页授权是一个涉及用户认证、信息交换和权限管理的重要环节。开发者需要理解OAuth2.0授权流程,并熟练使用微信提供的SDK和接口,才能实现安全、流畅的用户体验。通过WeixinApiDemo的...
总的来说,Python实现微信网页授权扫码登录涉及的关键技术包括OAuth2.0授权协议、微信开放平台API的使用、requests库的HTTP操作以及用户信息的本地存储和验证。理解并掌握这些知识点,能够帮助开发者构建安全、便捷...
企业微信开发实操考试涉及的具体知识点涵盖了企业微信的部署、API接口调用、通讯录管理、OAuth2认证流程、以及JS-SDK接口实现等多个方面。以下是对知识点的详细说明: 1. 企业微信私有化部署与CA数据中心集成: - ...
2. **引导用户授权**:在网页中添加链接,引导用户跳转到微信的授权页面。这个链接需要包含AppID、redirect_uri(回调URL)以及scope参数,例如`...
微信网页授权认证 根据微信官方文档,网页授权需要四个步骤, – 用户同意授权-获取code – 通过code 获取网页授权access_token – 通过code 获取网页授权access_token – 刷新token – 拉去用户信息scope为...
微信网页版协议是这些操作的基础,它包括了HTTP请求、JSON数据交换和OAuth2.0认证等关键部分。理解这些协议有助于我们编写自己的接口封装库。 对于`itchat`,它是Python社区中一个知名的微信个人号接口库,它提供了...
微信公众平台最近新推出微信认证,认证后可以获得高级接口权限,其中一个是OAuth2.0网页授权,很多朋友在使用这个的时候失败了或者无法理解其内容,希望我出个教程详细讲解一下,于是便有了这篇文章。 一、什么是...
10. **API集成**: 如果项目支持分享、登录等功能,可能需要与微信的开放平台API进行集成,这就需要熟悉OAuth认证流程和微信SDK的使用。 以上就是"swift-仿微信带有浮窗能力的微信浏览器"项目中涉及的主要技术点,...
4. **获取应用凭证**:通过AppID和AppSecret,开发者可以调用企业微信的OAuth2.0授权接口,获取Access Token和刷新Token。这两个凭证是后续调用其他API的基础。 5. **开发与测试**:使用企业微信提供的SDK和API文档...
例如,可能存在处理微信接口调用的库,如微信OAuth2认证、微信消息推送等。此外,还有可能包括数据加密解密、验证码生成、时间戳处理等通用功能的函数。 `smarty`文件夹暗示项目使用了Smarty模板引擎,这是一个PHP...
- **客户端(Client)**:请求受保护资源的一方,可以是移动应用、网页应用等多种类型的应用。 - **用户代理(User Agent)**:通常指用户使用的浏览器或其他网络工具。 - **资源所有者(Resource Owner)**:资源的拥有者...
然后在网站后端编写代码,调用微信的OAuth2.0授权接口,引导用户授权并获取用户OpenID,进而实现关注操作。 四、网站前端设计与集成 在网站前端,可以通过JavaScript或jQuery实现点击按钮弹出微信扫描界面。可以...