zoukankan      html  css  js  c++  java
  • 使用策略模式实现微信扫码登录

    本人该篇博客是按照完全小白的角度进行编写,从哪里登录查找开发API文档、开发原理及开发代码进行讲解,希望对有需要的博友有所帮助。

    一、准备工作

    (一)进入微信公众号测试平台

    https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login&token=579271486&lang=zh_CN

    (二)修改oauth2.0网页授权回调页面域名

     

    (三)微信网页授权API地址

    登录进入微信公众平台测试账号后,点击“网页授权获取用户基本信息”链接则进入对应API文档

     

    二、网页授权开发原理

    该原理API文档已说明,并每个步骤的参数都已明确说明

     

    三、代码编写

    (一)数据库代码

    向数据库中插入时要把APPID及授权码替换成你自己的。

    INSERT INTO `cyb_union_login` VALUES ('2', '腾讯微信联合登陆', 'cyb_weixin', 'weiXinUnionLoginStrategy', 'wx5c43fde3c9733d9e', 'b8b217126c33a5fb7074927d5e72a81a', 'http://www.cyb.com:7070/login/oauth/callback?unionPublicId=cyb_weixin', 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx5c43fde3c9733d9e&redirect_uri=http%3A%2F%2Fwww.cyb.com%3A7070%2Flogin%2Foauth%2Fcallback%3FunionPublicId%3Dmayikt_weixin&response_type=code&scope=snsapi_userinfo&state=111#wechat_redirect ', '1');

    (二)联合登录API接口

    import com.alibaba.fastjson.JSONObject;
    import com.cyb.base.BaseResponse;
    import io.swagger.annotations.Api;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    @Api(tags = "联合登陆接口")
    public interface MemberUnionLoginService {
    
    
        /**
         * 根据不同的联合登陆id
         *
         * @param unionPublicId
         * @return
         */
        @GetMapping("/unionLogin")
        BaseResponse<String> unionLogin(@RequestParam("unionPublicId") String unionPublicId);
    
        /**
         * 联合登陆回调接口
         *
         * @return
         */
        @GetMapping("/login/oauth/callback")
        BaseResponse<JSONObject> unionLoginCallback(@RequestParam("unionPublicId") String unionPublicId);
    
    }

    (三)联合登录接口实现类

    import com.alibaba.fastjson.JSONObject;
    import com.cyb.base.BaseApiService;
    import com.cyb.base.BaseResponse;
    import com.cyb.member.api.service.MemberUnionLoginService;
    import com.cyb.member.impl.entitydo.UnionLoginDo;
    import com.cyb.member.impl.mapper.UnionLoginMapper;
    import com.cyb.member.impl.strategy.UnionLoginStrategy;
    import com.cyb.utils.SpringContextUtils;
    import com.cyb.utils.TokenUtils;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    @RestController
    public class MemberUnionLoginServiceImpl extends BaseApiService implements MemberUnionLoginService {
    
        @Autowired
        private UnionLoginMapper unionLoginMapper;
        @Autowired
        private TokenUtils tokenUtils;
    
    
        @Override
        public BaseResponse<String> unionLogin(String unionPublicId) {
            if (StringUtils.isEmpty(unionPublicId)) {
                return setResultError("unionPublicId不能为空");
            }
            // 根据渠道id查询 联合基本信息
            UnionLoginDo unionLoginDo = unionLoginMapper.selectByUnionLoginId(unionPublicId);
            if (unionLoginDo == null) {
                return setResultError("该渠道可能已经关闭或者不存在");
            }
            String state = tokenUtils.createToken("member.unionLogin", "");
            String requestAddres = unionLoginDo.getRequestAddress() + "&state=" + state;
            JSONObject dataObjects = new JSONObject();
            dataObjects.put("requestAddres", requestAddres);
            return setResultSuccess(dataObjects);
    
        }
    
        @Override
        public BaseResponse<JSONObject> unionLoginCallback(String unionPublicId) {
            if (StringUtils.isEmpty(unionPublicId)) {
                return setResultError("unionPublicId不能为空");
            }
            // 根据渠道id查询 联合基本信息
            UnionLoginDo unionLoginDo = unionLoginMapper.selectByUnionLoginId(unionPublicId);
            if (unionLoginDo == null) {
                return setResultError("该渠道可能已经关闭或者不存在");
            }
            String unionBeanId = unionLoginDo.getUnionBeanId();
            if (StringUtils.isEmpty(unionBeanId)) {
                return setResultError("系统参数错误");
            }
            //  从Spring容器中根据beanid 查找到我们的策略类
            UnionLoginStrategy unionLoginStrategy = SpringContextUtils.getBean(unionBeanId, UnionLoginStrategy.class);
            // 根据当前线程获取request对象
            HttpServletRequest request = ((ServletRequestAttributes)
                    (RequestContextHolder.currentRequestAttributes())).getRequest();
            String openId = unionLoginStrategy.unionLoginCallback(request, unionLoginDo);
            if (StringUtils.isEmpty(openId)) {
                return setResultError("系统错误");
            }
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("openId", openId);
            jsonObject.put("unionPublicId", unionPublicId);
            String openToken = tokenUtils.createToken("cyb.unionLogin.", jsonObject.toJSONString());
            JSONObject dataToken = new JSONObject();
            dataToken.put("openToken", openToken);
            return setResultSuccess(dataToken);
        }
    }

    (四)联合登录策略接口

    /*
    * 联合登录策略接口
    * @Author 陈远波
    * @Date 2020-04-11
    */
    public interface UnionLoginStrategy {
        String unionLoginCallback(HttpServletRequest request, UnionLoginDo unionLoginDo);
    
        UserDo getDbOpenId(String openId);
    }

    (五)微信策略模式对应类

    import com.alibaba.fastjson.JSONObject;
    import com.cyb.http.HttpClientUtils;
    import com.cyb.member.impl.entitydo.UnionLoginDo;
    import com.cyb.member.impl.entitydo.UserDo;
    import com.cyb.member.impl.mapper.UserMapper;
    import com.cyb.member.impl.strategy.UnionLoginStrategy;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    
    /*
    * 
    * @Author 陈远波
    * @Date 2020-04-11
    */
    @Component
    public class WeiXinUnionLoginStrategy implements UnionLoginStrategy {
        @Value("${cyb.login.wx.accesstoken}")
        private String weixinAccessTokenAddres;
        @Autowired
        private UserMapper userMapper;
    
        @Override
        public String unionLoginCallback(HttpServletRequest request, UnionLoginDo unionLoginDo) {
            String code = request.getParameter("code");
            if (StringUtils.isEmpty(code)) {
                return null;
            }
            // 1.根据授权码获取accessToken 和openid
            // 获取微信newWeixinAccessTokenAddres
            String newWeixinAccessTokenAddres = weixinAccessTokenAddres.replace("APPID", unionLoginDo.getAppId() + "").replace("SECRET",
                    unionLoginDo.getAppKey()).replace("CODE", code);
            JSONObject accessTokenResult = HttpClientUtils.httpGet(newWeixinAccessTokenAddres);
            if (accessTokenResult == null) {
                return null;
            }
            boolean errcode = accessTokenResult.containsKey("errcode");
            if (errcode) {
                return null;
            }
            // 获取openid
            String openid = accessTokenResult.getString("openid");
            if (StringUtils.isEmpty(openid)) {
                return null;
            }
            return openid;
        }
    
        @Override
        public UserDo getDbOpenId(String openId) {
            return userMapper.selectByOpenId(openId);
        }
        
    }

    (六)联合登录mapper

    import com.cyb.member.impl.entitydo.UnionLoginDo;
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.annotations.Select;
    
    /*
    * 联合登录mapper
    * @Author 陈远波
    * @Date 2020-04-11
    */
    public interface UnionLoginMapper {
    
        @Select("SELECT ID AS ID ,union_name AS  unionname ,
    " +
                "union_public_id AS unionpublicid, union_bean_Id as unionBeanId, app_id AS appid,
    " +
                "app_key AS appkey,redirect_uri as redirecturi,
    " +
                "request_address as requestaddress,is_availability as isavailability
    " +
                " FROM meite_union_login where union_public_id=#{unionPublicId} and is_availability='1'")
        UnionLoginDo selectByUnionLoginId(@Param("unionPublicId") String unionPublicId);
    }

    (七)配置文件

    cyb:
       login:
          token:
            prefix: memberlogin
            channel: pc,android,ios
          qq:
            accesstoken: https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&client_id={client_id}&client_secret={client_secret}&code={code}&redirect_uri={redirect_uri}
            openid: https://graph.qq.com/oauth2.0/me?access_token=
          wx:
            accesstoken: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
    

      

    四、注意事项

    (一)请使用客户端进行测试

    在浏览器上使用后端生成的链接在浏览器上运行时会报“请使用客户端进行测试”

     

    报以下错误

     

    解决办法:

    进入https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

    下载stable Build 安装,将生成的requestAddres的链接在该模拟器中运行

     

    如果授权过一次,第二次则不会显示右侧弹框,如果想显示则在工具右上角清除缓存即可

    (二)Oauth2.0回调地址一致性

    Oauth2.0回调地址的域名要与数据库中设置的回调地址域名一致,不然会出现以下错误

    “当前账号未在公众平台绑定,无法调试此授权登录链接”

    如果对以上内容有疑问的可以私聊本人,转载请说明出处,本人博客地址为:https://www.cnblogs.com/chenyuanbo/

  • 相关阅读:
    python(九)、线程
    python(八)、进程
    python网络编程(二):网络编程之socket与socketserver
    20145226夏艺华 《Java程序设计》第6周学习总结
    20145226夏艺华《网络对抗》第一次实验拓展:shellcode注入+return-to-libc
    20145226夏艺华《网络对抗》免杀原理与实践
    20145226 《Java程序设计》第5周学习总结
    20145226 《Java程序设计》第4周学习总结
    20145226夏艺华 后门原理与实践
    20145226夏艺华 《Java程序设计》第3周学习总结
  • 原文地址:https://www.cnblogs.com/chenyuanbo/p/12681701.html
Copyright © 2011-2022 走看看