微信公衆號開發--第三章 註冊&簽到&校驗登錄

前言:本項目基於SSM,使用tomcat8、jdk8。

微信公衆號開發–第三章 註冊&簽到&校驗登錄

0、微信公衆號-用戶登錄&查看信息-時序圖

(高清html,文章末尾百度網盤鏈接自取)

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-iBgaVDe8-1590245139777)(/Users/mac/Documents/微信公衆號--時序圖V2.png)]

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

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-d6LBbGkf-1590245139779)(/Users/mac/Library/Application Support/typora-user-images/image-20200523185957392.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-auS837eA-1590245139780)(/Users/mac/Library/Application Support/typora-user-images/image-20200523190044919.png)]
點擊同意後,鏈接裏有code
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-I4E8iIpu-1590245139782)(/Users/mac/Library/Application Support/typora-user-images/image-20200523190138347.png)]

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、接口測試

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-tF2LaL27-1590245139783)(/Users/mac/Library/Application Support/typora-user-images/image-20200523215553618.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-B8YUFXOD-1590245139784)(/Users/mac/Library/Application Support/typora-user-images/image-20200523215939807.png)]

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、測試

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HuhwxGps-1590245139785)(/Users/mac/Library/Application Support/typora-user-images/image-20200523222001068.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zB25rSeC-1590245139786)(/Users/mac/Library/Application Support/typora-user-images/image-20200523222131734.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-U2klKNjm-1590245139787)(/Users/mac/Library/Application Support/typora-user-images/image-20200523222157923.png)]

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章