微信公众号开发-使用微信网页授权进行登录并加上过滤器判断是否已登录

  1. 首先你需要阅读一下这篇文档 微信开放文档
  2. 你需要去搞一个本地内网穿透,这样你就可以在本地进行调试你的代码。
    我用的穿透工具是这个:natapp
  3. 你还需要下载一个微信开发者工具 开发者工具下载,因为从手机上进行测试的话有时候微信会拦截你的URL,你就会收到如下一个页面。

微信公众号开发-使用微信网页授权进行登录并加上过滤器判断是否已登录_第1张图片

  1. 然后你需要去搞一个公众号的测试账号:微信公众号测试账号申请
  2. 废话不多说粘代码上来。代码参考 杨启盛的个人博客

一、使用拦截器判断用户是否近期登陆过项目
假如登录过能取到session可以直接放行,假如没有就去微信拿openid,调用链接中有回调地址会进入项目中从后台调用取openid的链接。

/**
 * @author 梁XL
 * @description
 * @date 2020/1/20
 */
public class UserInterceptor implements HandlerInterceptor {

    //在请求处理之前进行调用(Controller方法调用之前
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("preHandle被调用");
        // 校验
        Object openid = httpServletRequest.getSession().getAttribute("openid");
        // 判空
        if(openid==null){
            System.out.println("该次访问未获取到session中的openid");
            //生成静默授权获取openid跳转链接
            String url = "https://open.weixin.qq.com/connect/oauth2/authorize" +
                    "?appid=wxb61a17a1d03e1552&redirect_uri=http://abc.natappfree.cc/user/redirectGetUserInfo" +
                    "&response_type=code" +
                    "&scope=snsapi_userinfo" +
                    "&state=STATE#wechat_redirect";
            //跳转到微信授权页面
            httpServletResponse.sendRedirect(url);
            return false;
        }
        return true;
    }

    //请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle被调用");
    }

    //在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion被调用");
    }
}

二、注册拦截器并添加白名单。

/**
 * @author 梁XL
 * @description
 * @date 2020/1/11
 */
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {

    /**
     * 注册拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> list = new ArrayList<>();
        list.add("/wx");
        list.add("/user/redirectGetUserInfo");
        list.add("/pages/**");
        registry.addInterceptor(new UserInterceptor()).addPathPatterns("/**").excludePathPatterns(list);
    }
}

三、回调地址接口

// 微信公众号的 APPid
public final String APPID = "wx......";
// 微信公众号的 APPSecret
public String APPSECRET = "a8.......";


/**
     * @return java.lang.String
     * @throws
     * @description 获取用户token及基本信息
     * @author 梁XL
     * @date 2019/12/28
     */
    @GetMapping("/redirectGetUserInfo")
    public String getUserInfo(HttpServletRequest request, HttpServletResponse response) throws Exception {

        //如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE
        //获取code  code作为换取access_token的票据
        String code = request.getParameter("code");
        System.out.println("授权返回code信息---------:" + code);
        //第二步:通过code换取网页授权access_token (获取openid接口)
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + APPID
                + "&secret=" + APPSECRET
                + "&code=" + code
                + "&grant_type=authorization_code";

        //发送请求 get提交 拿code凭证去获取openid和access_token
        ResponseEntity<String> restTemplateForEntity = restTemplate.getForEntity(url, String.class);
        String getAccessTokenBody = restTemplateForEntity.getBody();
        HashMap<String, String> AccessTokenAndRefreshTokenMap = JsonMapper.string2Obj(getAccessTokenBody, new TypeReference<HashMap<String, String>>() {
        });

        String openid = AccessTokenAndRefreshTokenMap.get("openid");
        String access_token = AccessTokenAndRefreshTokenMap.get("access_token");  // 2H
        String refresh_token = AccessTokenAndRefreshTokenMap.get("refresh_token"); // 30天

        // 判断是否是第一次登录,假如是第一次登录就跳转注册网页,并保存openid
        // 判断用户是否是第一次登录本系统,这里放在了redis 假如你考虑到用户量过大,可以考虑换其他方式
        boolean isNotFirstLogin = redisUtils.hasKey(openid);
        if (!isNotFirstLogin) { //是第一次登录的用户
            log.info("未从缓存中获取到openid,该用户是第一次登录!");
            redisUtils.setStr(openid, refresh_token);
            log.info("将openid为:{},放入redis中!",openid);
            //获取用户拿到openid 和access_token去获取用户信息,在页面中进行业务处理,获取存储在数据库中:
            //第四步(获取用户接口)
            String infoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token
                    + "&openid=" + openid
                    + "&lang=zh_CN";

            ResponseEntity<String> userInfoEntity = restTemplate.getForEntity(infoUrl, String.class); // 乱码
            String userInfoStr = userInfoEntity.getBody();
            String userInfoMsg = new String(userInfoStr.getBytes("ISO-8859-1"), "UTF-8");
            HashMap<String, Object> userInfoMap = JsonMapper.string2Obj(userInfoMsg, new TypeReference<HashMap<String, Object>>() {
            });
            System.out.println(" 微信获取到的用户信息为userInfo------:" + userInfoMap.toString());
            // 保存用户信息进数据库
            userService.insertUser(userInfoMap);
            // 设置session
            request.getSession().setAttribute("openid",openid);
            // 跳转到用户注册页
            response.sendRedirect("http://xxx.com/...");// todo 此处为你系统中的注册页面,用来让用户输入你需要的数据,如电话、住址等等业务数据。

        }else{ // 不是第一次登录,只是session失效了
            log.info("该用户不是第一次登录,将openid放入session中,并跳转回首页!");
            request.getSession().setAttribute("openid",openid);
            response.sendRedirect("http://xxx.com"); // 跳转到首页去
        }

        return openid;
    }

以上为我个人想出的公众号后台项目结合微信网页授权的方式,如你有更好的方式欢迎您在下方进行评论,让我也学习学习涨涨经验,谢谢!

你可能感兴趣的:(后端)