微信登陆Web应用解决方案
2017-04-14 11:45
246 查看
http://blog.csdn.net/u013410747/article/category/6098729
1.PC端
2.移动端
3.接入流程参考微信登录Web技术接入参考
注意写入事物回滚机制(因为涉及到操作多张表避免问题,)
接入微信登陆参考代码
1.微信开放平台回调函数
2.后端自动登陆
3.读取用户的微信绑定状态
4.用户取消绑定微信号
5.用户绑定手机号
6.与微信平台交互的代码
1.PC端
2.移动端
3.接入流程参考微信登录Web技术接入参考
注意写入事物回滚机制(因为涉及到操作多张表避免问题,)
接入微信登陆参考代码
1.微信开放平台回调函数
/** * @param code 微信开放平台重定向这里,携带的code码 * @param state 来自PC端还是Mobile端 * * @author simon * @date 2016/02/24 */ @GET @Path("wxlogin") public void wxlogin(@QueryParam("code") String code, @QueryParam("state") String state, @Context HttpServletRequest request, @Context HttpServletResponse response) throws Exception { if (!StringUtils.isEmpty(code)) { //1.根据code请求access_token Map<String, Object> map = CodeUtils.get_access_token(code); String access_token = map.get("access_token").toString(); String openid = map.get("openid").toString(); //2.使用access_token去请求用户信息 Map<String, Object> userinfoMap = CodeUtils.get_userinfo(access_token, openid); if (LuoboAppContext.currentUser() != null) { WeichatBind weichatBind = new WeichatBind(); weichatBind.setUnionid(userinfoMap.get("unionid").toString()); weichatBind.setUserId(LuoboAppContext.currentUser().getId()); userService.createBind(weichatBind);//完成绑定 if(state.equals("01")){ response.sendRedirect("http://www.jkgst.com/main.html#!/user/base");//重定向到PC端页面 }else{ response.sendRedirect("http://www.jkgst.com/m/#!/user/base");//重定向到移动端页面 } } else { //当前为登陆操作,去绑定表查询该微信号是否已经绑定过 WeichatBind weichatBind = userService.getByUnionid(userinfoMap.get("unionid").toString()); if (weichatBind != null) { //用户已经绑定过 User user = userService.findById(weichatBind.getUserId()); //完成模拟登陆,重定向到主页面即可 autoLogin(request,response,user.getUsername(),state); } else { //用户第一次绑定,先去绑定手机号,先把userinfoMap放入session中 request.getSession().setAttribute("userinfoMap", userinfoMap); //重定向到绑定手机号页面 if(state.equals("01")){ //来自PC response.sendRedirect("http://www.jkgst.com/main.html#!/bind");//去PC页面完成绑定 }else{ //来自移动端 response.sendRedirect("http://www.jkgst.com/m/#!/bind");//去手机页面完成绑定 } } } } }
2.后端自动登陆
/** * 后端自动登陆 * * @param type PC 或 Mobile * * @author simon * @date 2016/02/26 * */ public void autoLogin(HttpServletRequest request, HttpServletResponse response,String username,String type) throws Exception { ObjectWriter viewWriter = this.mapper.writerWithView(JsonViews.Self.class); ResponseBean rb = new ResponseBean(); try { UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, "",userDetails.getAuthorities()); //Authentication authentication = this.authManager.authenticate(authenticationToken); SecurityContextHolder.getContext().setAuthentication(authenticationToken); /* * Reload user as password of authentication principal will be null after authorization and * password is needed for token generation */ // String ip = request.getRemoteAddr(); // String token = TokenUtils.createToken(userDetails , ip); try { UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent")); LoginLog ll = new LoginLog(); ll.setUserId(((User) userDetails).getId()); ll.setIpAddress(request.getRemoteAddr()); ll.setLoginTime(new Date()); ll.setBrowser(userAgent.getBrowser().getName()); ll.setDevice(userAgent.getOperatingSystem().getDeviceType().getName()); loginLogDao.save(ll); } catch (Exception e) { logger.error("fail to save login log", e); e.printStackTrace(); } //ADD TO SESSION request.getSession().setAttribute(Constants.Authentication.CURRENT_USER, userDetails); List<Map> menuList = new ArrayList<Map>(); if (type != null && !"".equals(type)) { User user=(User) userDetails; menuList = menuDao.findByUser(user, type); } rb.setData(MapUtils.asMap(MapUtils.any("user", userDetails), MapUtils.any("menus", menuList)));//MapUtils.any("token", token), String userinfo = URLEncoder.encode(viewWriter.writeValueAsString(userDetails), "utf-8"); Cookie cookie=new Cookie("user",userinfo); cookie.setPath("/"); response.addCookie(cookie); } catch (Exception e) { logger.error("faile to login", e); rb.setMessage(100001, "username or password is invalid."); }finally { rb.setData(true); response.getWriter().print(rb);//返回响应信息 } }
3.读取用户的微信绑定状态
/** * 读取用户的微信绑定状态 * * @author simon * @date 2016/02/25 */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("weichatState") public ResponseBean weichatState() { ResponseBean responseBean = new ResponseBean(); try{ //根据当前登陆的用户id找到对应的绑定表的信息 WeichatBind weichatBind = userService.getByUserId(LuoboAppContext.currentUser().getId()); if(weichatBind!=null) responseBean.setData(weichatBind); else responseBean.setErrorCode(-1); }catch (Exception e){ responseBean.setErrorCode(-1); } return responseBean; }
4.用户取消绑定微信号
/** * 用户取消绑定微信号 * * @author simon * @date 2016/02/25 */ @GET @Produces(MediaType.APPLICATION_JSON) @Path("unbind") public ResponseBean UnBindWeixin() { ResponseBean responseBean = new ResponseBean(); //根据当前登陆的用户id找到对应的绑定表的信息 try { WeichatBind weichatBind = userService.getByUserId(LuoboAppContext.currentUser().getId()); userService.removeBind(weichatBind.getId()); }catch (Exception e){ responseBean.setErrorCode(-1); } return responseBean; }
5.用户绑定手机号
/** * @描述 用户绑定手机号 * * @param mobileNo 绑定的手机号 * @param type PC 或 Mobile * * @author simon * @date 2016/02/29 */ @GET @Path("bind") public void BindWeixin(@QueryParam("mobileNo") Long mobileNo, @Context HttpServletRequest request, @Context HttpServletResponse response, @QueryParam("type") String type) throws Exception { //1.根据要绑定的手机号信息找对应的user信息 User user = userService.getUserByMobileNo(mobileNo); //2.从session获得在上一步中放入 Map<String, Object> userinfoMap = (Map<String, Object>)request.getSession().getAttribute("userinfoMap"); if(userinfoMap==null){ ResponseBean responseBean=new ResponseBean(); responseBean.setErrorCode(-2); response.getWriter().print(responseBean);//出现异常 return; } if(user==null){//用户不存在,要生成账号 User newuser=new User(); newuser.setMobileNo(mobileNo); newuser.setName(userinfoMap.get("nickname").toString()); newuser.setEnabled(true); newuser.setStatus("1"); if(type.equals("PC")){ newuser.setRegDevice("01"); }else{ newuser.setRegDevice("02"); } newuser.setUsername(""+mobileNo); String password=CodeUtils.generateRandomString(6);//随机密码 newuser.setPassword(this.passwordEncoder.encode(password)); newuser.addRole(Constants.Role.USER); user= this.userDao.save(newuser);//生成账号 //微信登陆注册成功计算获得积分 try { int obtainPoints = pointsService.calculatePointsForUserRegister(user.getId()); } catch (Exception e) { logger.error("error occurs: ", e); // 记录错误日志 } // 注册成功的同时,新增一个对应的简历记录 MicroCv cv = new MicroCv(); cv.setUserId(user.getId()); cv.setName(user.getName()); cv.setPhone(user.getMobileNo()); cv.setEmail(user.getEmail()); cv.setIsSelf(true); microCvDao.save(cv); //注册成功的同时,要新增一个对应的积分记录 //如果注册时带了邀请码,则给邀请人加积分 // if (!StringUtils.isEmpty(bean.getToken())) { // try { // pointsService.calculatePointsForInviteRegister(bean.getToken(), user.getName(), String.valueOf(user.getMobileNo())); // } catch (Exception e) { // logger.error("error occurs: ", e); // // 记录错误日志 // } // } WeichatBind weichatBind = new WeichatBind(); weichatBind.setUnionid(userinfoMap.get("unionid").toString()); weichatBind.setUserId(user.getId()); //完成绑定 WeichatBind weichatBind1=userService.createBind(weichatBind); //完成模拟登陆 autoLogin(request,response,user.getUsername(),type); }else{ //已经存在,找到账号完成绑定,再模拟登陆 WeichatBind weichatBind = new WeichatBind(); weichatBind.setUnionid(userinfoMap.get("unionid").toString()); weichatBind.setUserId(user.getId()); WeichatBind weichatBind1=userService.createBind(weichatBind);//3.完成绑定 //完成模拟登陆 if(type.equals("PC")){ autoLogin(request,response,user.getUsername(),"PC"); }else{ autoLogin(request,response,user.getUsername(),null); } } }
6.与微信平台交互的代码
package com.bigluobo.utils; import com.google.gson.*; import com.google.gson.reflect.TypeToken; import java.io.*; import java.net.*; import java.util.*; /** * Created by Henry on 2015/12/15. */ public class CodeUtils { private static final String appid="******************"; private static final String secret="******************"; //获得随机值 public static final String generateRandomString(int length) { String allChar = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; StringBuffer sb = new StringBuffer(); Random random = new Random(); for (int i = 0; i < length; i++) { sb.append(allChar.charAt(random.nextInt(allChar.length()))); } return sb.toString(); } /** * 通过code向微信开放平台请求access_token * * @param code * */ public static Map<String,Object> get_access_token(String code) { //拼接请求access_token的链接 String url = "https://api.weixin.qq.com/sns/oauth2/access_token"; String params="appid="+appid+"&secret="+secret+"&code="+ code+"&grant_type=authorization_code"; String resultJson = sendGet(url, params); Map<String,Object> map = parseData(resultJson);//将返回的json数据转换为Map结构存储 /*示例: *{ "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE", "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" } * */ return map; } /** * 函数名称: refresh_access_token * * 函数描述: access_token超时,使用refresh_token重新获得一个access_token * * @param refresh_token * @return Map<String, String> */ public static Map<String,Object> refresh_access_token(String refresh_token){ //access_token超时,此时需要重新获得一个access_token。 String url_access="https://api.weixin.qq.com/sns/oauth2/refresh_token"; StringBuffer params_access=new StringBuffer() .append("appid=").append(appid) .append("&grant_type=refresh_token") .append("&refresh_token=").append(refresh_token); String resultJson=sendGet(url_access,params_access.toString()); Map<String,Object> map = parseData(resultJson);//将返回的json数据转换为Map结构存储 /* * { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" } * */ return map; } /** * 函数名称: get_userinfo * * 函数描述: 通过access_token去获取用户的信息 * * @param access_token * @return Map<String, String> */ public static Map<String,Object> get_userinfo(String access_token,String openid){ //access_token超时,此时需要重新获得一个access_token。 String url_userinfo="https://api.weixin.qq.com/sns/userinfo"; StringBuffer params_userinfo=new StringBuffer() .append("access_token=").append(access_token) .append("&openid=").append(openid); String resultJson=sendGet(url_userinfo,params_userinfo.toString()); Map<String,Object> map = parseData(resultJson);//将返回的json数据转换为Map结构存储 if(map.size()>3){ //已经正确获取到用户信息 /* * { "openid":"OPENID", "nickname":"NICKNAME", "sex":1, "province":"PROVINCE", "city":"CITY", "country":"COUNTRY", "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0", "privilege":[ "PRIVILEGE1", "PRIVILEGE2" ], "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL" } * */ return map; }else{ if(map.get("errcode").equals("42001")){ //access_token超时,需要重新获得access_token超时,再请求用户信息 Map<String,Object> map1= refresh_access_token(access_token); String access_token2=map1.get("access_token").toString(); String openid2=map1.get("openid").toString(); //刷新以后重新获取用户的信息 get_userinfo(access_token2,openid2); } } return map; } /** * 函数名称: parseData * 函数描述: 将json字符串转换为Map<String, String>结构 * * @param data * @return Map<String, String> */ private static Map<String, Object> parseData(String data) { GsonBuilder gb = new GsonBuilder(); Gson g = gb.create(); Map<String, Object> map = g.fromJson(data, new TypeToken<Map<String, Object>>() { }.getType()); return map; } /** * 向指定URL发送GET方法的请求 * * @param url 发送请求的URL * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return URL 所代表远程资源的响应结果 */ public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" + param; URL realUrl = new URL(urlNameString); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立实际的连接 connection.connect(); // 获取所有响应头字段 Map<String, List<String>> map = connection.getHeaderFields(); // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader( connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); e.printStackTrace(); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; } }
相关文章推荐
- 微信登陆Web应用解决方案
- web应用的跨域访问解决方案
- Web登陆模块的常见解决方案及一些注意事项
- 基于Web服务的应用、解决方案和开发平台
- web应用的跨域访问解决方案 (1)
- 最近准备研究下高负载Web应用的解决方案,先保存些相关网站
- 医院微信应用解决方案
- web应用的跨域访问解决方案
- JForum SSO - 整合已有的web应用 - JForum单点登陆原理与配置
- Web应用乱码(2)__原因以及解决方案详解
- Java WEB 应用字符编码解决方案
- web应用的跨域访问解决方案
- Web应用中重复提交的问题的三种解决方案
- Web应用乱码(1)__解决方案
- 架构Web Service:基于Web服务的应用、解决方案和开发平台
- Cognos ReportNet 与WEB应用同时登陆
- web应用的跨域访问解决方案
- 关于web应用中跨域问题的解决方案,并特别针对移动方向提出一些解决方案
- 数字证书在WEB应用中实现登陆
- Web应用中重复提交的问题的三种解决方案