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

本文介绍了如何在SpringMVC中实现微信企业号的OAuth2验证,通过创建OAuth2Interceptor拦截器,检查请求是否需要OAuth2认证,并在需要时重定向到授权页面。同时提供了相关配置和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

企业应用中的URL链接(包括自定义菜单或者消息中的链接),可以通过OAuth2.0来获取员工的身份信息。
注意,此URL的域名,必须完全匹配企业应用设置项中的'可信域名',否则获取用户信息时会返回50001错误码。
可信域名设置不包含"http://",只需域名或IP即可。
OAuth2验证可以使用多种方式,此处使用注解方式。设计思路是在需要获取用户信息的GET请求上添加注解,然后在调用的时候判断是否包含此注解,然后做处理流程。
每次请求包含2种情况:
1.不需要获取用户信息,直接跳转到指定视图;
2.需要获取用户信息,此处分2种情况:
a.session中存储了之前获取的用户信息,则直接跳转到指定视图;
b.session中不包含用户信息,则需要构造带回调参数的URL去微信API服务器获取code参数,然后通过code参数调用API换取Userid并保存到session,然后再次跳转到初始请求的视图页面。


具体处理流程如下图:



此处源码包括:微信企业号的接入及消息的简单处理,在此基础上添加OAuth2的验证实例。
源码下载地址:http://download.csdn.NET/detail/rzg813/8015527

具体实现代码:

创建拦截器:OAuth2Interceptor

[java]  view plain  copy
 print ?
  1. package org.oms.qiye.interceptor;  
  2.   
  3. import java.io.UnsupportedEncodingException;  
  4. import java.lang.reflect.Method;  
  5.   
  6. import javax.servlet.http.HttpServletRequest;  
  7. import javax.servlet.http.HttpServletResponse;  
  8. import javax.servlet.http.HttpSession;  
  9.   
  10. import org.springframework.web.method.HandlerMethod;  
  11. import org.springframework.web.servlet.HandlerInterceptor;  
  12. import org.springframework.web.servlet.ModelAndView;  
  13.   
  14. public class OAuth2Interceptor implements HandlerInterceptor {  
  15.   
  16.     /** 
  17.      * 在DispatcherServlet完全处理完请求后被调用 
  18.      * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion() 
  19.      */  
  20.     @Override  
  21.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  
  22.         System.out.println("**执行顺序: 3、afterCompletion**");  
  23.   
  24.     }  
  25.   
  26.     /** 
  27.      * 在业务处理器处理请求执行完成后,生成视图之前执行的动作 
  28.      */  
  29.     @Override  
  30.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView modelAndView) throws Exception {  
  31.         System.out.println("**执行顺序: 2、postHandle**");  
  32.   
  33.     }  
  34.   
  35.     /** 
  36.      * 在业务处理器处理请求之前被调用 如果返回false 从当前的拦截器往回执行所有拦截器的afterCompletion(),再退出拦截器链 
  37.      * 如果返回true 执行下一个拦截器,直到所有的拦截器都执行完毕 再执行被拦截的Controller 然后进入拦截器链, 
  38.      * 从最后一个拦截器往回执行所有的postHandle() 接着再从最后一个拦截器往回执行所有的afterCompletion() 
  39.      */  
  40.     @Override  
  41.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
  42.         System.out.println("**执行顺序: 1、preHandle**");  
  43.         String url = request.getRequestURL().toString();  
  44.   
  45.         HttpSession session = request.getSession();  
  46.         // 先判断是否有注解  
  47.   
  48.         HandlerMethod handlerMethod = (HandlerMethod) handler;  
  49.         Method method = handlerMethod.getMethod();  
  50.         OAuthRequired annotation = method.getAnnotation(OAuthRequired.class);  
  51.         if (annotation != null) {  
  52.             System.out.println("OAuthRequired:你的访问需要获取登录信息!");  
  53.             Object objUid = session.getAttribute("UserId");  
  54.             if (objUid == null) {  
  55.                 String resultUrl = request.getRequestURL().toString();  
  56.                 String param=request.getQueryString();  
  57.                 if(param!=null){  
  58.                     resultUrl+= "?" + param;  
  59.                 }  
  60.                 System.out.println("resultUrl="+resultUrl);  
  61.                 try {  
  62.                     resultUrl = java.net.URLEncoder.encode(resultUrl, "utf-8");  
  63.                 } catch (UnsupportedEncodingException e) {  
  64.                     e.printStackTrace();  
  65.                 }  
  66.                 //请求的路径  
  67.                 String contextPath=request.getContextPath();  
  68.                 response.sendRedirect(contextPath + "/oauth2.do?resultUrl=" + resultUrl);  
  69.                 return false;  
  70.             }  
  71.   
  72.         }  
  73.         return true;  
  74.     }  
  75.   
  76. }  

验证OAuth2注解OAuthRequired
[java]  view plain  copy
 print ?
  1. package org.oms.qiye.interceptor;  
  2.   
  3. import java.lang.annotation.*;  
  4. /** 
  5.  * 验证OAuth2注解 
  6.  * @author Sunlight 
  7.  * 
  8.  */  
  9. @Retention(RetentionPolicy.RUNTIME)  
  10. @Target(ElementType.METHOD)  
  11. public @interface OAuthRequired {  
  12.       
  13. }  

常量类,此处可以替换为持久化数据读取;
[java]  view plain  copy
 print ?
  1. package org.oms.qiye.util;  
  2.   
  3. public class Constants {  
  4.     /** 
  5.      * 常量说明: 
  6.      * 此处定义的常量需要持久化,可以保存在数据库中,在需要的地方读取。 
  7.      * 在多企业号中,最好以每个应用来定义。 
  8.      */  
  9.     public static final int AGENTID = 1;  
  10.     public static final String TOKEN = "sunlight";  
  11.     public static final String CORPID = "你的企业号ID";  
  12.     public static final String Secret = "你的企业号_ACCESS_TOKEN";  
  13.     public static final String encodingAESKey = "s8vFF4f6AWay3uAdJh79WD6imaam4BV6Kl4eL4UzgfM";  
  14. }  

OAuth2 处理控制器OAuth2Controller
[java]  view plain  copy
 print ?
  1. package org.oms.qiye.web;  
  2.   
  3. import java.io.UnsupportedEncodingException;  
  4.   
  5. import javax.servlet.http.HttpServletRequest;  
  6. import javax.servlet.http.HttpSession;  
  7.   
  8. import org.oms.qiye.pojo.AccessToken;  
  9. import org.oms.qiye.util.Constants;  
  10. import org.oms.qiye.util.QiYeUtil;  
  11. import org.oms.qiye.util.Result;  
  12. import org.springframework.stereotype.Controller;  
  13. import org.springframework.web.bind.annotation.RequestMapping;  
  14. import org.springframework.web.bind.annotation.RequestParam;  
  15. /** 
  16.  * OAuth2 处理控制器 
  17.  * @author Sunlight 
  18.  * 
  19.  */  
  20. @Controller  
  21. public class OAuth2Controller {  
  22.     /** 
  23.      * 构造参数并将请求重定向到微信API获取登录信息 
  24.      *  
  25.      * @param index 
  26.      * @return 
  27.      */  
  28.     @RequestMapping(value = { "/oauth2.do""/oauth2" })  
  29.     public String Oauth2API(HttpServletRequest request, @RequestParam String resultUrl) {  
  30.         // 此处可以添加获取持久化的数据,如企业号id等相关信息  
  31.         String CropId = Constants.CORPID;  
  32.         String redirectUrl = "";  
  33.         if (resultUrl != null) {  
  34.             String reqUrl =request.getLocalAddr();  
  35.             String backUrl ="http://" + reqUrl + "/oauth2url.do?oauth2url=" + resultUrl;  
  36.             System.out.println("backUrl="+backUrl);  
  37.             redirectUrl = oAuth2Url(CropId, backUrl);  
  38.         }  
  39.         return "redirect:" + redirectUrl;  
  40.     }  
  41.   
  42.     /** 
  43.      * 根据code获取Userid后跳转到需要带用户信息的最终页面 
  44.      *  
  45.      * @param request 
  46.      * @param code 
  47.      *            获取微信重定向到自己设置的URL中code参数 
  48.      * @param oauth2url 
  49.      *            跳转到最终页面的地址 
  50.      * @return 
  51.      */  
  52.     @RequestMapping(value = { "/oauth2url.do" })  
  53.     public String Oauth2MeUrl(HttpServletRequest request, @RequestParam String code, @RequestParam String oauth2url) {  
  54.         AccessToken accessToken = QiYeUtil.getAccessToken(Constants.CORPID, Constants.Secret);  
  55.         HttpSession session = request.getSession();  
  56.         if (accessToken != null && accessToken.getToken() != null) {  
  57.             String Userid = getMemberGuidByCode(accessToken.getToken(), code, Constants.AGENTID);  
  58.             if (Userid != null) {  
  59.                 session.setAttribute("UserId", Userid);  
  60.             }  
  61.         }  
  62.         // 这里简单处理,存储到session中  
  63.         return "redirect:" + oauth2url;  
  64.     }  
  65.   
  66.     /** 
  67.      * 构造带员工身份信息的URL 
  68.      *  
  69.      * @param corpid 
  70.      *            企业id 
  71.      * @param redirect_uri 
  72.      *            授权后重定向的回调链接地址,请使用urlencode对链接进行处理 
  73.      * @param state 
  74.      *            重定向后会带上state参数,企业可以填写a-zA-Z0-9的参数值 
  75.      * @return 
  76.      */  
  77.     private String oAuth2Url(String corpid, String redirect_uri) {  
  78.         try {  
  79.             redirect_uri = java.net.URLEncoder.encode(redirect_uri, "utf-8");  
  80.         } catch (UnsupportedEncodingException e) {  
  81.             e.printStackTrace();  
  82.         }  
  83.         String oauth2Url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + corpid + "&redirect_uri=" + redirect_uri  
  84.                 + "&response_type=code&scope=snsapi_base&state=sunlight#wechat_redirect";  
  85.         System.out.println("oauth2Url=" + oauth2Url);  
  86.         return oauth2Url;  
  87.     }  
  88.   
  89.     /** 
  90.      * 调用接口获取用户信息 
  91.      *  
  92.      * @param token 
  93.      * @param code 
  94.      * @param agentId 
  95.      * @return 
  96.      * @throws SQLException 
  97.      * @throws RemoteException 
  98.      */  
  99.     public String getMemberGuidByCode(String token, String code, int agentId) {  
  100.         System.out.println("code==" + code + "\ntoken=" + token + "\nagentid=" + agentId);  
  101.         Result<String> result = QiYeUtil.oAuth2GetUserByCode(token, code, agentId);  
  102.         System.out.println("result=" + result);  
  103.         if (result.getErrcode() == "0") {  
  104.             if (result.getObj() != null) {  
  105.                 // 此处可以通过微信授权用code还钱的Userid查询自己本地服务器中的数据  
  106.                 return result.getObj();  
  107.             }  
  108.         }  
  109.         return "";  
  110.     }  
  111.   
  112. }  

需要验证OAuth2控制器UserController
[java]  view plain  copy
 print ?
  1. package org.oms.qiye.web;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4. import javax.servlet.http.HttpSession;  
  5. import org.oms.qiye.interceptor.OAuthRequired;  
  6. import org.springframework.stereotype.Controller;  
  7. import org.springframework.ui.Model;  
  8. import org.springframework.web.bind.annotation.RequestMapping;  
  9. /** 
  10.  * 需要验证OAuth2控制器 
  11.  * @author Sunlight 
  12.  * 
  13.  */  
  14. @Controller  
  15. public class UserController {  
  16.     /** 
  17.      * 加载个人信息,此处添加了@OAuthRequired注解 
  18.      * @param model 
  19.      * @return 
  20.      */  
  21.     @RequestMapping(value={"/userInfo.do"})  
  22.     @OAuthRequired  
  23.     public String load(HttpServletRequest request,Model model){  
  24.         System.out.println("Load a User!");  
  25.         HttpSession session = request.getSession();  
  26.         model.addAttribute("Userid", session.getAttribute("Userid"));  
  27.         return "user";  
  28.     }  
  29. }  

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

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

返回结果处理类Result.class

枚举EnumMethod.class

以上类不在列出,在其他文章已存在!

处理页面user.jsp:

[html]  view plain  copy
 print ?
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  4. <html>  
  5. <head>  
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  7. <title>Model And List</title>  
  8. </head>  
  9. <body>  
  10.     <h1>Welcome To SpringMVC! This is OAuth2 UserInfo</h1>  
  11.     <h3>获取到的Userid是:${UserId}</h3>  
  12. </body>  
  13. </html>  

SpringMVC配置文件:mvc-servlet.xml
[html]  view plain  copy
 print ?
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"  
  4.     xmlns:context="http://www.springframework.org/schema/context"  
  5.     xmlns:mvc="http://www.springframework.org/schema/mvc"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/beans   
  7.     http://www.springframework.org/schema/beans/spring-beans-3.2.xsd   
  8.     http://www.springframework.org/schema/tx   
  9.     http://www.springframework.org/schema/tx/spring-tx-3.2.xsd  
  10.     http://www.springframework.org/schema/context  
  11.     http://www.springframework.org/schema/context/spring-context-3.2.xsd  
  12.     http://www.springframework.org/schema/mvc  
  13.     http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">  
  14.   
  15.     <context:component-scan base-package="org.oms.qiye.web"></context:component-scan>  
  16.     <mvc:annotation-driven />  
  17.   
  18.     <bean  
  19.         class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
  20.         <property name="prefix" value="/WEB-INF/jsp/"></property>  
  21.         <property name="suffix" value=".jsp"></property>  
  22.     </bean>  
  23.   
  24.     <!-- 静态文件处理 -->  
  25.     <mvc:resources mapping="/images/**" location="/images/" />  
  26.     <mvc:resources mapping="/js/**" location="/js/" />  
  27.     <mvc:resources mapping="/css/**" location="/css/" />  
  28.   
  29.     <!-- OAuth2拦截器 -->  
  30.     <mvc:interceptors>  
  31.         <mvc:interceptor>  
  32.             <!-- 对所有的请求拦截使用/** ,对某个模块下的请求拦截使用:/myPath/* -->  
  33.             <mvc:mapping path="/**" />  
  34.             <ref bean="oauth2Interceptor" />  
  35.         </mvc:interceptor>  
  36.     </mvc:interceptors>  
  37.     <bean id="oauth2Interceptor" class="org.oms.qiye.interceptor.OAuth2Interceptor">  
  38.     </bean>  
  39. </beans>  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值