基于java的微信公众号授权登录

实现业务:微信授权登录,调用后台接口,获取用户信息,实现自己系统中的用户登录业务。

Ⅰ.开发前准备一网页授权回调域名

首先要在公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名,微信公众平台测试号支持本地ip,这里在微信测试号中测试,微信公众平台测试地址

基于java的微信公众号授权登录_第1张图片
微信截图_20181128111028.png

具体而言,微信浏览器中网页授权流程分为四步
1.用户进入授权页面,同意授权,获取code
2.通过code换取网页授权access_token(与基础支持中的access_token不同)
3.如果需要,开发者可以刷新网页授权access_token,避免过期
4.通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

Ⅱ.具体开发流程
这里采用拦截器形式对需要用户信息的业务进行拦截,实现自己系统中的用户登录业务

package com.jianshu.web.interceptor;
import com.jianshu.common.utils.Constants;
import com.jianshu.common.utils.StringUtils;
import com.jianshu.common.utils.SystemKeys;
import com.jianshu.modules.frontBase.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;

public class OAuth2Interceptor extends HandlerInterceptorAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(OAuth2Interceptor.class);

    // 微信授权地址
    private static String authUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
    // 微信授权方式 :应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid)
    // snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,
    // 即使在未关注的情况下,只要用户授权,也能获取其信息
    private static String SCOPE = "snsapi_userinfo";
    // private static String SCOPE = "snsapi_base";
    //微信授权获取登录凭证code接口
    private static String REDIRECT_URI = Constants.CONTEXT_DOMAIN + "wow/auth?redirect=REDIRECT_URL";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        Cookie[] cookies = request.getCookies();
        String openid = "";
        if (cookies != null) {
            //这里是根据cookie的key获取value
            openid = SystemKeys.getUserInfo(cookies);
        }
        if (StringUtils.isBlank(openid)) {
            LOGGER.debug("###### wechat auth login !");
            String queryString = request.getQueryString();
            String redirectUrl = "";
            if(StringUtils.isNotBlank(queryString)){
                redirectUrl = request.getRequestURL() + "?" + request.getQueryString();
            }
            String url = authUrl.replace("APPID", Constants.APPID).replace("SCOPE", SCOPE).replace("REDIRECT_URI", URLEncoder.encode(REDIRECT_URI.replace("REDIRECT_URL", redirectUrl), "utf-8"));
            response.sendRedirect(url);
            return false;
        }
       
        return super.preHandle(request, response, handler);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

微信授权获取登录凭证code接口
  @RequestMapping("wow/main")
    public String main(HttpServletRequest request, HttpServletResponse response, Model model) {
        return "web/main/index";
    }
@RequestMapping("wow/auth")
    public String auth(HttpServletRequest request, HttpServletResponse response) {
        String code = request.getParameter("code");
        String openid = "";
        String redirectUrl = request.getParameter("redirect");
        try {
            String res = WXUtils.getOpenId(Constants.APPID, Constants.APPSECRET, code);
            LOGGER.info("openId from wx res:" + res);
            JSONObject json = JSONObject.fromObject(res);
            openid = json.getString("openid");
            String token = json.getString("access_token");
            if (StringUtils.isNotEmpty(openid)) {
                //用户登录
                User user = apiUserService.login(openid, token);
                if (user != null) {
                    //用户信息存储到cookie
                    Cookie userCookie = new Cookie(Constants.User.COOKIE_KEY, openid);
                    userCookie.setMaxAge(-1);   //设置为“0”或负值时,关闭浏览器才会清除cookie
                    userCookie.setPath("/");
                    response.addCookie(userCookie);
                }
            }
        } catch (Exception e) {
            LOGGER.error("程序错误", e);
            return "web/common/error";
        }
        if (StringUtils.isBlank(redirectUrl)) {
            //redirect 地址为空的话默认跳转到主页
            redirectUrl = "/wow/main";
        }
        return "redirect:" + redirectUrl;
    }
自己系统中的用户登录业务逻辑
package com.jianshu.web.frontBase.service;

import com.jianshu.common.service.BaseService;
import com.jianshu.common.utils.*;
import com.jianshu.modules.frontBase.dao.UserDao;
import com.jianshu.modules.frontBase.model.User;
import com.jianshu.modules.frontBase.model.vo.UserVo;
import com.jianshu.web.common.SessionUser;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

/**
 * userService
 * 
 * @author ritian
 * @date 2018年4月14日
 */
@Service
public class ApiUserService extends BaseService {
    @Resource
    private UserDao userDao;

    //根据openid 登录
    public User login(String openid, String token) {
        User user = this.findByOpenid(openid);
       //user为空则保存至数据库中
        if (user == null) {
            //根据token及openid获取用户信息
            JSONObject json = WXUtils.getUserInfo(token, openid);
            if(json != null){
              user = getUser(json);
              user.setOpenid(openid);
             this.save(user);
           }
        }
        cacheUser(user);
        return user;

    }

    public User get(int id){
        return userDao.get(id);
    }

    /**
     * 缓存用户信息,
     *
     * @param user 需要被缓存的用户
     * @return 服务器缓存的用户信息
     */
    private void cacheUser(User user) {
        CacheUtils.put(Constants.Cache.USER_CACHE, user.getOpenid(), user);
    }

    public User findByOpenid(String openid) {
        return userDao.findByOpenid(openid);
    }

    /**
     * 保存
     */
    public void save(User t) {
        userDao.save(t);
    }
    private User getUser(JSONObject json) {
        User user = new User();
        user.setHeadImgUrl(json.optString("headimgurl"));
        user.setNickname(json.getString("nickname"));
        user.setCreateTime(new Date());
        user.setProvince(json.optString("province"));
        user.setCity(json.optString("city"));
        user.setGender(json.optInt("sex"));
        return user;
    }
}

相关工具类,根据token及openid获取用户信息

参考微信官方文档一第四步:拉取用户信息(需scope为 snsapi_userinfo)

package com.ccamazing.common.utils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import com.github.pagehelper.util.StringUtil;
import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;

/**
 * 微信工具类(公众号开发)
 * 
 * @author ritian
 * @date 2018年4月14日
 */
public class WXUtils {

    // 获取access_token的接口地址(GET) 限2000(次/天)
    private final static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
    // 获取jsapi_ticket的接口地址(GET) 限2000(次/天)
    private final static String jsapi_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi";
    // 获取openId的接口地址
    private final static String oauth_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    // 获取网页授权微信用户信息地址
    private final static String sns_userinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESSTOKEN&openid=OPENID&lang=zh_CN";

    // 获取微信卡券api_ticket 接口地址
    private final static String api_ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESSTOKEN&type=wx_card";

    private static final Logger logger = LoggerFactory.getLogger(WXUtils.class);
    



    /**
     * 获取网页授权微信用户信息
     */
    public static JSONObject getUserInfo(String token, String openId) {
        try {
            // 通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。
            String url = sns_userinfo_url.replace("ACCESSTOKEN", token).replace(
                    "OPENID", openId);
            String res = HttpUtils.doGet(url);
            return JSONObject.fromObject(res);
        } catch (Exception e) {
            logger.error("用户授权获取用户信息失败!", e);
        }
        return null;
    }
}

spring-mvc拦截器配置文件


    
        
             
            
            
            
            
        
    

到这里基本上就完成了微信授权网页登录了。至于其他业务扩展,可根据具体需求自己实现~~

你可能感兴趣的:(基于java的微信公众号授权登录)