微信企业号OAuth2验证接口(使用SpringMVC)



企业应用中的URL链接(包含自己定义菜单或者消息中的链接)。能够通过OAuth2.0来获取员工的身份信息。

注意。此URL的域名,必须全然匹配企业应用设置项中的'可信域名'。否则获取用户信息时会返回50001错误码。

可信域名设置不包括"http://",仅仅需域名或IP就可以。

OAuth2验证能够使用多种方式,此处使用注解方式。设计思路是在须要获取用户信息的GET请求上加入注解。然后在调用的时候推断是否包括此注解,然后做处理流程。

每次请求包括2种情况:

1.不须要获取用户信息,直接跳转到指定视图;

2.须要获取用户信息,此处分2种情况:

a.session中存储了之前获取的用户信息,则直接跳转到指定视图。

b.session中不包括用户信息。则须要构造带回调參数的URL去微信APIserver获取code參数,然后通过code參数调用API换取Userid并保存到session。然后再次跳转到初始请求的视图页面。

详细处理流程例如以下图:

此处源代码包含:微信企业号的接入及消息的简单处理,在此基础上加入OAuth2的验证实例。

源代码下载地址:http://download.csdn.net/detail/rzg813/8015527



详细实现代码:

创建拦截器:OAuth2Interceptor

package org.oms.qiye.interceptor;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; public class OAuth2Interceptor implements HandlerInterceptor { /**
* 在DispatcherServlet全然处理完请求后被调用
* 当有拦截器抛出异常时,会从当前拦截器往回运行全部的拦截器的afterCompletion()
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("**运行顺序: 3、afterCompletion**"); } /**
* 在业务处理器处理请求运行完毕后,生成视图之前运行的动作
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView modelAndView) throws Exception {
System.out.println("**运行顺序: 2、postHandle**"); } /**
* 在业务处理器处理请求之前被调用 假设返回false 从当前的拦截器往回运行全部拦截器的afterCompletion(),再退出拦截器链
* 假设返回true 运行下一个拦截器,直到全部的拦截器都运行完毕 再运行被拦截的Controller 然后进入拦截器链,
* 从最后一个拦截器往回运行全部的postHandle() 接着再从最后一个拦截器往回运行全部的afterCompletion()
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("**运行顺序: 1、preHandle**");
String url = request.getRequestURL().toString(); HttpSession session = request.getSession();
// 先推断是否有注解 HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
OAuthRequired annotation = method.getAnnotation(OAuthRequired.class);
if (annotation != null) {
System.out.println("OAuthRequired:你的訪问须要获取登录信息! ");
Object objUid = session.getAttribute("UserId");
if (objUid == null) {
String resultUrl = request.getRequestURL().toString();
String param=request.getQueryString();
if(param!=null){
resultUrl+= "? " + param;
}
System.out.println("resultUrl="+resultUrl);
try {
resultUrl = java.net.URLEncoder.encode(resultUrl, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//请求的路径
String contextPath=request.getContextPath();
response.sendRedirect(contextPath + "/oauth2.do?resultUrl=" + resultUrl);
return false;
} }
return true;
} }

验证OAuth2注解OAuthRequired

package org.oms.qiye.interceptor;

import java.lang.annotation.*;
/**
* 验证OAuth2注解
* @author Sunlight
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface OAuthRequired { }

常量类。此处能够替换为持久化数据读取。

package org.oms.qiye.util;

public class Constants {
/**
* 常量说明:
* 此处定义的常量须要持久化,能够保存在数据库中,在须要的地方读取。
* 在多企业号中。最好以每一个应用来定义。
*/
public static final int AGENTID = 1;
public static final String TOKEN = "sunlight";
public static final String CORPID = "你的企业号ID";
public static final String Secret = "你的企业号_ACCESS_TOKEN";
public static final String encodingAESKey = "s8vFF4f6AWay3uAdJh79WD6imaam4BV6Kl4eL4UzgfM";
}

OAuth2 处理控制器OAuth2Controller

package org.oms.qiye.web;

import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import org.oms.qiye.pojo.AccessToken;
import org.oms.qiye.util.Constants;
import org.oms.qiye.util.QiYeUtil;
import org.oms.qiye.util.Result;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* OAuth2 处理控制器
* @author Sunlight
*
*/
@Controller
public class OAuth2Controller {
/**
* 构造參数并将请求重定向到微信API获取登录信息
*
* @param index
* @return
*/
@RequestMapping(value = { "/oauth2.do", "/oauth2" })
public String Oauth2API(HttpServletRequest request, @RequestParam String resultUrl) {
// 此处能够加入获取持久化的数据,如企业号id等相关信息
String CropId = Constants.CORPID;
String redirectUrl = "";
if (resultUrl != null) {
String reqUrl =request.getLocalAddr();
String backUrl ="http://" + reqUrl + "/oauth2url.do? oauth2url=" + resultUrl;
System.out.println("backUrl="+backUrl);
redirectUrl = oAuth2Url(CropId, backUrl);
}
return "redirect:" + redirectUrl;
} /**
* 依据code获取Userid后跳转到须要带用户信息的终于页面
*
* @param request
* @param code
* 获取微信重定向到自己设置的URL中code參数
* @param oauth2url
* 跳转到终于页面的地址
* @return
*/
@RequestMapping(value = { "/oauth2url.do" })
public String Oauth2MeUrl(HttpServletRequest request, @RequestParam String code, @RequestParam String oauth2url) {
AccessToken accessToken = QiYeUtil.getAccessToken(Constants.CORPID, Constants.Secret);
HttpSession session = request.getSession();
if (accessToken != null && accessToken.getToken() != null) {
String Userid = getMemberGuidByCode(accessToken.getToken(), code, Constants.AGENTID);
if (Userid != null) {
session.setAttribute("UserId", Userid);
}
}
// 这里简单处理,存储到session中
return "redirect:" + oauth2url;
} /**
* 构造带员工身份信息的URL
*
* @param corpid
* 企业id
* @param redirect_uri
* 授权后重定向的回调链接地址,请使用urlencode对链接进行处理
* @param state
* 重定向后会带上state參数,企业能够填写a-zA-Z0-9的參数值
* @return
*/
private String oAuth2Url(String corpid, String redirect_uri) {
try {
redirect_uri = java.net.URLEncoder.encode(redirect_uri, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String oauth2Url = "https://open.weixin.qq.com/connect/oauth2/authorize? appid=" + corpid + "&redirect_uri=" + redirect_uri
+ "&response_type=code&scope=snsapi_base&state=sunlight#wechat_redirect";
System.out.println("oauth2Url=" + oauth2Url);
return oauth2Url;
} /**
* 调用接口获取用户信息
*
* @param token
* @param code
* @param agentId
* @return
* @throws SQLException
* @throws RemoteException
*/
public String getMemberGuidByCode(String token, String code, int agentId) {
System.out.println("code==" + code + "\ntoken=" + token + "\nagentid=" + agentId);
Result<String> result = QiYeUtil.oAuth2GetUserByCode(token, code, agentId);
System.out.println("result=" + result);
if (result.getErrcode() == "0") {
if (result.getObj() != null) {
// 此处能够通过微信授权用code还钱的Userid查询自己本地server中的数据
return result.getObj();
}
}
return "";
} }

须要验证OAuth2控制器UserController

package org.oms.qiye.web;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.oms.qiye.interceptor.OAuthRequired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* 须要验证OAuth2控制器
* @author Sunlight
*
*/
@Controller
public class UserController {
/**
* 载入个人信息,此处加入了@OAuthRequired注解
* @param model
* @return
*/
@RequestMapping(value={"/userInfo.do"})
@OAuthRequired
public String load(HttpServletRequest request,Model model){
System.out.println("Load a User!");
HttpSession session = request.getSession();
model.addAttribute("Userid", session.getAttribute("Userid"));
return "user";
}
}

发起https请求并获取结果HttpRequestUtil.class

微信企业号调用类 {"errcode":0,"errmsg":"ok"} 此结果表示调用方法成功返回QiYeUtil.class

返回结果处理类Result.class

枚举EnumMethod.class

以上类不在列出。在其它文章已存在!

处理页面user.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Model And List</title>
</head>
<body>
<h1>Welcome To SpringMVC! This is OAuth2 UserInfo</h1>
<h3>获取到的Userid是:${UserId}</h3>
</body>
</html>

SpringMVC配置文件:mvc-servlet.xml

<?

xml version="1.0" encoding="UTF-8"?

>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <context:component-scan base-package="org.oms.qiye.web"></context:component-scan>
<mvc:annotation-driven /> <bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean> <!-- 静态文件处理 -->
<mvc:resources mapping="/images/**" location="/images/" />
<mvc:resources mapping="/js/**" location="/js/" />
<mvc:resources mapping="/css/**" location="/css/" /> <!-- OAuth2拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 对全部的请求拦截使用/** ,对某个模块下的请求拦截使用:/myPath/* -->
<mvc:mapping path="/**" />
<ref bean="oauth2Interceptor" />
</mvc:interceptor>
</mvc:interceptors>
<bean id="oauth2Interceptor" class="org.oms.qiye.interceptor.OAuth2Interceptor">
</bean>
</beans>

server測试结果图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvb21zdmlw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">



手机微信client測试结果图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvb21zdmlw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

转载请注明出处。以免慘不忍睹!

技术交流请增加QQ群:点击链接增加群【微信企业号开发交流】:http://jq.qq.com/?

_wv=1027&k=RgbtOX

QQ群:89714226

微信企业号OAuth2验证接口实例(使用SpringMVC)的更多相关文章

  1. 《微信开发日志》之OAuth2验证接口

    OAuth2接口说明: 企业应用中的URL链接(包括自定义菜单或者消息中的链接),可以通过OAuth2.0验证接口来获取员工的身份信息. 通过此接口获取用户身份会有一定的时间开销.对于频繁获取用户身份 ...

  2. asp.net 、C#实现微信企业号OAuth2认证

    以微信企业号作为入口的应用,几乎都会遇到需要应用系统中个人信息和微信用户关联问题.从而进行其他业务处理.目前所做项目采取在企业号通讯录添加自定义字段存入应用系统用户信息表中唯一标识UserGuid进行 ...

  3. 微信企业号OAuth2.0验证接口来获取成员的身份信息

    <?php $appid = "请输入您企业的appid"; $secret = "请输入您企业的secreat"; if (!isset($_GET[' ...

  4. 微信企业号-JS-SDK图像接口

    使用JS-SDK需要进行四步  主要是步骤二和步骤三,步骤二需要配置,步骤三具体使用相关接口,这里以使用图像接口为例 php页面代码主要用来完成步骤二,也就是配置接口 public function ...

  5. C#开发微信门户及应用(20)-微信企业号的菜单管理

    前面几篇陆续介绍了很多微信企业号的相关操作,企业号和公众号一样都可以自定义菜单,因此他们也可以通过API进行菜单的创建.获取列表.删除的操作,因此本篇继续探讨这个主体,介绍企业号的菜单管理操作. 菜单 ...

  6. 微信企业号开发:微信用户信息和web网页的session的关系

         微信企业号的用户是须要验证的,因此能关注企业号的用户事实上就是已经通过验证的用户.但企业应用中打开一个网页,在这个网页中怎样依据微信用户的信息创建web应用中最长使用的session呢?微信 ...

  7. 微信公众平台企业号验证接口、回调 PHP版

    微信公众平台企业号验证接口.回调 PHP版,本人为了解决这个企业号的验证和发送消息的问题,整整研究了几天时间,由于微信企业号刚推出来,网上资料太少了!后来在一些朋友的帮助下和本人重复调试完好下,最终整 ...

  8. 关于微信中JS-SDK的接口验证过程详细说明

    最近在做微信的企业服务号,刚开始通过个人的测试平台进行开发,使用了自定义菜单,自定义菜单包含两个功能:1.扫一扫,通过扫描我们账单的二维码,绑定账户和账单的关系:2.打开我们系统的账单查询页面,查询账 ...

  9. Force.com微信企业号开发系列(一) - 启用二次验证

    微信于9月份推出企业号后引起了业界不小的反响,许多企业都在思索企业号将如何影响企业的运营,从本文开始,我将详细阐述微信企业号开发的相关知识,而本文将着重介绍如何实现更高安全机制的二次验证. 申请企业体 ...

随机推荐

  1. find命令查找包含指定内容的文件

    find / | xargs grep function 查找系统根目录下面的所有文件的内容中包含有function字符串的文件列表. find .|xargs grep xfind . -exec ...

  2. mysq在某一刻同时获取主从库的位置点

    在从库进行锁表操作flush table with read lock, 通过show slave status\G 获取对应主库的位置点: show slave status\G********** ...

  3. 【C】——网络编程-聊天室

    功能介绍: 此demo是基于TCP套接字编程,目的是实现一个聊天室效果.类似于QQ群效果,如果上线可以通知其他好友,下线也会通知其他好友. 需要用的技术: 一.socket编程. 1> sock ...

  4. compareTo返回值为-1 、 1 、 0 的排序问题

    1.什么是Comparable接口 此接口强行对实现它的每个类的对象进行整体排序.此排序被称为该类的自然排序 ,类的 compareTo 方法被称为它的自然比较方法 .实现此接口的对象列表(和数组)可 ...

  5. tf变换(1)

    TF库的目的是实现系统中任一个点在所有坐标系之间的坐标变换,也就是说,只要给定一个坐标系下的一个点的坐标,就能获得这个点在其他坐标系的坐标. 使用tf功能包,a. 监听tf变换: 接收并缓存系统中发布 ...

  6. Altium Designer 规则设置

    设计规则设置 Designer Rules Check(DRC) Electrical 电气规则.安全间距,线网连接等 Routing 布线,线宽.过孔形状尺寸.布线拓扑.布线层.封装出线等 SMT ...

  7. USB学习笔记连载(十二):USB描述符

    USB设备是端口,接口,配置的集合,USB协议是以各种USB描述符来表征USB设备的功能.计算机通过这些描述符来获得USB设备的功能. USB描述符包括: USB标准设备描述符,USB集线器描述符.H ...

  8. USB2.0学习笔记连载(五):EZ-USB重要寄存器的配置

    本篇博客主要讲解EZ-USB一些重要寄存器的配置,首先对于本篇博客所讲的内容,读者应该到官网上去下载相关的手册,其中包括<EZ-USB Technical Reference Manual> ...

  9. 【转】android中的数据存取-方式一:preference(配置)

    这种方式应该是用起来最简单的Android读写外部数据的方法了.他的用法基本上和J2SE(java.util.prefs.Preferences)中的用法一样,以一种简单. 透明的方式来保存一些用户个 ...

  10. Linux入门基础教程之Linux下软件安装

    Linux入门基础教程之Linux下软件安装 一.在线安装: sudo apt-get install 即可安装 如果在安装完后无法用Tab键补全命令,可以执行: source ~/.zshrc AP ...