spring boot实现微信的网页授权
来源:互联网 发布:冒险岛游戏数据 编辑:程序博客网 时间:2024/06/05 00:23
spring boot实现微信的网页授权
使用spring boot实现简单微信授权登录
这是第一篇在csdn发表的博客
一,添加maven依赖
<dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-mp</artifactId> <version>2.8.0</version></dependency>
二,添加微信相关的配置信息
这里使用的是第三方sdk来MP_OAuth2网页授权功能,想了解可以看这个
微信的授权登录需要用到公众号的appid和secret,我用的是测试号,将这些配置信息写到application.yml中
wechat: appid: wx6*************6b secret: 0******************************6
创建一个bean来接收配置信息,set和get方法这里省略了
@Component@ConfigurationProperties(prefix = "wechat")public class WechatAccountConfig { /**公众号appid*/ private String appid; /**公众号secret*/ private String secret;
用户在微信客户端中访问第三方网页,公众号就可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑,使用该sdk获取用户信息的步骤是首先构造网页授权url,当用户同意授权后,会回调所设置的url并把authorization code传过来,然后用这个code获得access token,其中也包含用户的openid等信息,代码如下:
首先将appid和secret放进一个WxMpService,创建一个WxMpService对象
@Componentpublic class WechatMpConfig { @Autowired private WechatAccountConfig accountConfig; @Bean public WxMpService wxMpService(){ //创建WxMpService实例并设置appid和sectret WxMpService wxMpService = new WxMpServiceImpl(); //这里的设置方式是跟着这个sdk的文档写的 wxMpService.setWxMpConfigStorage(wxConfigProvider()); return wxMpService; } @Bean public WxMpConfigStorage wxConfigProvider(){ WxMpInMemoryConfigStorage wxConfigProvider = new WxMpInMemoryConfigStorage(); wxConfigProvider.setAppId(accountConfig.getAppid()); wxConfigProvider.setSecret(accountConfig.getSecret()); return wxConfigProvider; }}
三,编写微信授权代码获取openid
import lombok.extern.slf4j.Slf4j;import me.chanjar.weixin.common.api.WxConsts;import me.chanjar.weixin.common.exception.WxErrorException;import me.chanjar.weixin.mp.api.WxMpService;import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import wang.linge.config.ProjectUrlConfig;import wang.linge.enums.ResultEnum;import wang.linge.exception.MyException;import java.net.URLEncoder;/** * Created by linge on 2017/10/5. */@Controller@RequestMapping("/wechat")@Slf4jpublic class WechatController { @Autowired private WxMpService wxMpService; @Autowired private WxMpService wxOpenService; @Autowired private ProjectUrlConfig projectUrlConfig; /** * 访问这个时便会发起微信的网页授权 * @param returnUrl 发起授权是可携带的一个参数,我这里用的是下面将要用到的login()的地址,将获取到的openid传递过去 * @return */ @GetMapping("/authorize") public String authorize(@RequestParam("returnUrl") String returnUrl) { //设置回调地址 String url = "http://localhost/wechat/userInfo"; String redirectUrl = wxMpService.oauth2buildAuthorizationUrl(url, WxConsts.OAUTH2_SCOPE_BASE, URLEncoder.encode(returnUrl)); return "redirect:" + redirectUrl; } //微信回调时访问的地址 这里获得code和之前所设置的returnUrl @GetMapping("/userInfo") public String userInfo(@RequestParam("code") String code, @RequestParam("state") String returnUrl) { WxMpOAuth2AccessToken wxMpOAuth2AccessToken = new WxMpOAuth2AccessToken(); try { wxMpOAuth2AccessToken = wxMpService.oauth2getAccessToken(code); } catch (WxErrorException e) { log.error("【微信网页授权】{}", e); //抛出异常 自定义的 方便处理 可自己定义 throw new MyException(ResultEnum.WECHAT_MP_ERROR, e.getError().getErrorMsg()); } String openId = wxMpOAuth2AccessToken.getOpenId(); return "redirect:" + returnUrl + "?openid=" + openId; }}
四,编写login方法将当前登录用户的信息存入当前会话中
@GetMapping("login")public ModelAndView login(@RequestParam("openid") String openid, HttpServletResponse response, Map<String,Object> map){ //1,openid 去和数据库里面的数据匹配验证 这里只是演示就删掉没有了 //2,设置token至cookie 并设置过期时间 CookieUtil.set(response,CookieConstant.TOKEN,token,CookieConstant.EXPIRE); return new ModelAndView("redirect:http://localhost/index")); }
import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.HashMap;import java.util.Map;/** * Cookie工具类 * Created by linge on 2017/10/17. */public class CookieUtil { public static void set(HttpServletResponse response, String name,String value, int maxAge){ Cookie cookie = new Cookie(name, value); cookie.setPath("/"); cookie.setMaxAge(maxAge); response.addCookie(cookie); } /** * 获取Cookie * @param request * @param name * @return */ public static Cookie get(HttpServletRequest request, String name){ Map<String, Cookie> map = readCookieMap(request); if(map.containsKey(name)){ return map.get(name); }else{ return null; } } /** * 将cookie封装成map * @param request * @return */ public static Map<String,Cookie> readCookieMap(HttpServletRequest request){ Cookie[] cookies = request.getCookies(); Map<String,Cookie> map = new HashMap<>(); if(cookies != null){ for(Cookie cookie : cookies){ map.put(cookie.getName(),cookie); } } return map; }}
/** * Cookie常量 * Created by linge on 2017/10/17. */public interface CookieConstant { String TOKEN = "token"; Integer EXPIRE = 7200 ;}
五,使用切面拦截所有请求验证是否已验证登录
import lombok.extern.slf4j.Slf4j;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.stereotype.Component;import org.springframework.util.StringUtils;import org.springframework.web.context.request.RequestAttributes;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import wang.linge.constant.CookieConstant;import wang.linge.constant.RedisConstant;import wang.linge.exception.AuthorizeException;import wang.linge.utils.CookieUtil;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;/** * Created by linge on 2017/10/17. */@Aspect@Component@Slf4jpublic class AuthorizeAspect { @Autowired private StringRedisTemplate redisTemplate; @Pointcut("execution(public * wang.linge.controller.*.*(..))"+ "&& !execution(public * wang.linge.controller.UserController.*(..))") public void verify(){ } @Before("verify()") public void doVerify(){ ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); HttpServletRequest request = requestAttributes.getRequest(); Cookie cookie = CookieUtil.get(request, CookieConstant.TOKEN); if(cookie == null){ log.warn("【登录校验】,无法在cookie中查找到token的值"); throw new AuthorizeException(); } String tokenValue = redisTemplate.opsForValue().get(String.format(RedisConstant.TOKEN_PREFIX, cookie.getValue())); if(StringUtils.isEmpty(tokenValue)){ log.warn("【登录校验】,无法在redis中查找到token的值"); throw new AuthorizeException(); } }}
六,处理未登录的异常,引导到登陆链接
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpStatus;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.ResponseStatus;import org.springframework.web.servlet.ModelAndView;import wang.linge.config.ProjectUrlConfig;import wang.linge.exception.Exception;import wang.linge.exception.AuthorizeException;/** * Created by linge on 2017/10/18. */@ControllerAdvicepublic class ExceptionHandler { //为了方便将一些url写到配置里去 这里就不贴出来 可不用这个直接写地址或者仿照之前微信appid的配置写这个配置 @Autowired private ProjectUrlConfig urlConfig; @ExceptionHandler(AuthorizeException.class) public ModelAndView handlerAuthorizeException(){ return new ModelAndView("redirect:" .concat(urlConfig.getWechatOpenAuthorize()) .concat("/wechat/qrAuthorize") .concat("?returnUrl=") .concat("http://localhost/login")); }}
参考资料:
微信官方文档
所用到的第三方SDK
阅读全文
0 0
- spring boot实现微信的网页授权
- Spring Boot 微信-网页授权获取用户信息
- 微信网页授权Java实现
- 微信网页授权Java实现
- 微信网页授权
- 微信网页授权
- 微信网页授权
- 微信网页授权
- 微信网页授权
- 微信网页授权
- 微信网页授权
- 微信网页授权
- 微信网页授权
- 微信网页授权
- 微信网页授权
- 微信网页授权
- 微信网页授权
- [微信开发] 微信网页授权Java实现
- Gym 101612L Little Difference 因子分解
- Postgres + Postgis Windows安装
- 原生js面向对象开发打砖块游戏,用代码怀念儿时经典
- Java多线程之并发容器(五)
- ubuntu上runsv/runit小记
- spring boot实现微信的网页授权
- tomcat的端口修改后在eclipse中自动恢复成原来的端口
- Mybatis四大神器之三-删除
- debug没问题,release有问题的情况
- 数字阵列麦克风处理技术概述
- JAVA设计模式——单例模式
- Linux下open与fopen的区别
- RAC下的local_listener和Remote_listener
- select标签基本使用