微信公众号开发--第三章 注册&签到&校验登录

前言:本项目基于SSM,使用tomcat8、jdk8。

目录

微信公众号开发–第三章 注册&签到&校验登录

0、微信公众号-用户登录&查看信息-时序图

(高清html,文章末尾百度网盘链接自取)

微信公众号开发--第三章 注册&签到&校验登录

1、获取用户基本信息&注册(对应时序图的步骤1-7)

1.1、接口代码(微信后端接口)

/**
 * @DESCRIPTION : 与微信第三方交互,从而获取用户信息。
 *  备注--1、本地启动前端服务获取code:
 *  由于微信第三方的限制,获取code的操作,应该只能在微信客户端实现(官方文档貌似这个意思,我没写过test请求过)。
 *  参考博文
 *  https://blog.csdn.net/Sharylala/article/details/105495723
 *  的页面操作部分,获取code,而后将code作为入参调接口getUserInfo
 *
 *  备注--2、访问请求链接获取code:
 *  (自己微信号要关注自己的测试号二维码)
 *  2.1、本地域名,设为 local.sharylala.test
 *  2.2、回调地址,设为 local.sharylala.test
 *  2.3、在微信开发者工具上,访问
 *  https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
 *  其中APPID改写为你的appid值,REDIRECT_URI改写成你的 http://回调域名,
 *  scope为snsapi_base 时 scope=snsapi_base
 *  scope为snsapi_userinfo 时 scope=snsapi_userinfo(我测试只用过这个),
 *  state,重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节。eg: state=123
 *  2.4、点击"同意"
 *  2.5、自动跳转页面的地址上的code,五分钟有效
 *
 *
 *
 * @AUTHOR Sharylala
 * @DATE : 2020/5/21 10:12 下午
 * @param bean
 * @param request
 * @return: com.sharylala.common.util.Result
 */
@RequestMapping(value = "/getUserInfo", method = RequestMethod.POST)
@ResponseBody
public Result getUserInfo(@RequestBody UserBean bean, HttpServletRequest request) throws Exception {

    log.info("----------AuthController:getUserInfo----------");
    String code = bean.getCode();
    if (code == null || "".equals(code)) {
        return result(Constants.RESULT_MESSAGE_EMPTY,"code不能为空", null);
    }
    String openid = null;
    JSONObject userInfo = new JSONObject();
    WeChatAuth wa = new WeChatAuth(appid,appsecret);

    /**
     * 1、获取前端传来的code。
     * 请求https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
     * 获取access_token和openid。
     * */
    openid = wa.getOpenidByAuth(code);

    if (null != openid) {
        /**
         * 2、根据access_token和openid,
         * 请求https://api.weixin.qq.com/sns/userinfo?access_token=TOKEN&openid=OPENID&lang=zh_CN
         * 拉取用户信息。
         * */
        userInfo = wa.getUserInfoByOpenid(openid);
       
        //将拉取的基本信息存进用户表,略
    } else {
        return error("获取openid失败");
    }
    if (null == userInfo) {
        userInfo = new JSONObject();
        log.info("======微信用户信息获取失败====");
        return error("获取用户信息获取失败");
    }
    return ok("获取用户信息获取成功",userInfo);
}

1.2、接口测试

1.2.1、获取code

微信公众号开发--第三章 注册&签到&校验登录
微信公众号开发--第三章 注册&签到&校验登录
点击同意后,链接里有code
微信公众号开发--第三章 注册&签到&校验登录

1.2.2、获取用户信息

微信公众号开发--第三章 注册&签到&校验登录

2、签到(对应时序图的步骤8-11)

2.1、接口代码(简化版,微信后端和后台接口)

微信后端签到接口common/sgin

/**
 * @DESCRIPTION : 登陆验证获取tokenid接口
 * @AUTHOR Sharylala
 * @DATE : 2020/5/22 7:11 下午
 * @param session
 * @return: com.sharylala.common.util.Result
 */
@ResponseBody
@RequestMapping(value = "/sign", method = RequestMethod.GET, produces = "application/json")
public Result sign(HttpSession session) {
    String url = Interface.getInstance().get("sign");
    String result = (String) getWebClient(url, String.class);
    log.info("---------sign:{}------", result);
    JSONObject jsonResult = Common.strToJSONObject(result);
    if (null == jsonResult) {
        return error("接口请求错误");
    }
    String statusCode = jsonResult.getString("statusCode");
    if ("200".equals(statusCode)) {
        try {
            log.info("======sessionId:{}======", session.getId());
            JedisUtil.setValue(session.getId() + "_tokenid", jsonResult.getString("data"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return result(statusCode, jsonResult.getString("message"), jsonResult.getString("data"));
}

后台签到接口user/sign

/**
 * @DESCRIPTION :获取tokenid
 * @param request
 * @param response
 * @return: com.sharylala.common.util.Result
 */
@RequestMapping(value = "/sign", method = RequestMethod.GET, produces = "application/json")
@ResponseBody
public Result sign(@Context HttpServletRequest request, @Context HttpServletResponse response) {
    String result = Constants.RESULT_MESSAGE_ERROR;
    String message = "获取tokenid失败";
    String tokenid = "";
    String ip = "";
    try {
        tokenid = Constants.WECHAT_SERVICE_TOKENNAME + CommUtil.getUUID();
        ip = CommUtil.getIpAddress(request);
        JedisUtil.setValue(tokenid, ip, Constants.WECHAT_SERVICE_TIMEOUT);
        result = Constants.RESULT_MESSAGE_SUCCESS;
        message = "获取tokenid成功";
        return result(result, message, tokenid);
    } catch (Exception e) {
        logger.info("tokenid is : " + tokenid + "===========ip is: " + ip);
        logger.error(ip + "获取tokenid失败!   /n  异常信息:" + e.getMessage(), e);
    } finally {
        logger.info("tokenid is : " + tokenid + "===========ip is: " + ip);
    }
    logger.info(message);
    return result(result, message);
}

2.2、接口测试

微信公众号开发--第三章 注册&签到&校验登录
微信公众号开发--第三章 注册&签到&校验登录

3、校验登录

3.1、配置web.xml

<!-- 校验tokenid拦截器-->
<filter>
    <filter-name>AuthFilter</filter-name>
    <filter-class>com.sharylala.modules.wechatservice.filter.AuthFilter</filter-class>
    <init-param>
        <param-name>anonUrl</param-name>
        <param-value>/auth/getUserInfo,/common/sign,/user/sign</param-value><!--过滤器添加例外url用,隔开-->
    </init-param>
    <init-param>
        <param-name>authc</param-name><!--本系统拦截验证选项-->
        <param-value>true</param-value><!--true需要拦截鉴权,安全性高,拦截未登录及无权限等访问;开发时可填false-->
    </init-param>
</filter>
<filter-mapping>
    <filter-name>AuthFilter</filter-name>
    <url-pattern>/fileService/*</url-pattern><!--需要拦截验证的请求-->
    <url-pattern>/business/*</url-pattern>
</filter-mapping>

3.2、实现Filter的拦截类代码

/**
 * @DESCRIPTION: 校验tokenid拦截类
 * @AUTHOR Sharylala
 * @DATE 2020/5/23 8:41 下午
 */

public class AuthFilter implements Filter {
    public final static Logger logger = LoggerFactory.getLogger(AuthFilter.class);

    private boolean authc; //是否开启拦截
    private String[] anonUrlArray; //不拦截的url
    private final PathMatcher pathMatcher = new AntPathMatcher();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String authcStr = filterConfig.getInitParameter("authc");
        if (StringUtils.isNotBlank(authcStr)){
            this.authc = Boolean.parseBoolean(authcStr);
        }
        String anonUrl = filterConfig.getInitParameter("anonUrl");
        if (StringUtils.isNotBlank(anonUrl)) {
            this.anonUrlArray = anonUrl.split(",");
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException  {
        try {
            if (!authc) {
                chain.doFilter(request, response);
                return;
            } else {
                HttpServletRequest httpRequest = (HttpServletRequest) request;
                String currentURL = httpRequest.getServletPath();
                //过滤白名单
                if (isWhiteURL(currentURL)){
                    chain.doFilter(request, response);
                    return;
                }
                Cookie[] cookies = httpRequest.getCookies();
                if (cookies != null) {
                    for (Cookie cookie : cookies) {
                        if ("tokenid".equals(cookie.getName()) && StringUtils.isNotBlank(cookie.getValue())) {
                            //根据tokenid的值,去查redis有没有对应的ip(在签到接口里value就是用request的ip搞的)
                            String tokenid = cookie.getValue();
                            String redis = JedisUtil.getValue(tokenid);
                            if (StringUtils.isBlank(redis)) {
                                response.getWriter().print(JSON.toJSONString(new Result(Constants.RESULT_MESSAGE_EXIT, "登录超时,请重新登录")));
                                return;
                            }
                            String ip = CommUtil.getIpAddress(httpRequest);
                            //与request的ip对比
                            if (ip.equals(redis)) {
                                logger.info("====ip.equals(redis)====ip: " + ip + " redis: " + redis);
                                chain.doFilter(request, response);
                                return;
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("AuthFilter拦截器doFilter方法异常,", e);
        }
        response.getWriter().print(JSON.toJSONString(new Result("403", "please log in first!", null)));
    }

    @Override
    public void destroy() {
        //TODO Auto-generated method stub
    }

    private boolean isWhiteURL(String currentURL) {
        for (String whiteURL : anonUrlArray) {
            if (pathMatcher.match(whiteURL, currentURL)) {
                return true;
            }
        }
        return false;
    }

}

3.3、测试

微信公众号开发--第三章 注册&签到&校验登录
微信公众号开发--第三章 注册&签到&校验登录
微信公众号开发--第三章 注册&签到&校验登录

链接:https://pan.baidu.com/s/16-Wq-4VWXbJ_fkQupgLwag 密码:bj2k

上一篇:Go语言(学习)——接口源码分析


下一篇:SpringCloud 服务间调用添加header