微信公众号授权登录,整合spring security
公司的业务需求,对接了微信公众号授权,通过微信公众号的接口拿到用户信息进行业务系统的登录,话不多说上代码,我的实现方式是整合了spingSecurity
首先是接口
@PostMapping("/official/login")
@ApiOperation(value = "公众号授权登录", notes = "此接口返回系统的token")
public AjaxResult officialLogin(@RequestBody String code){
AjaxResult ajax = AjaxResult.success();
String token = mobileLoginService.officialLogin(code);
ajax.put(Constants.TOKEN, token);
return ajax;
}
然后是service
/**
* 公众号登录
* @param code 授权码
* @return token
*/
public String officialLogin(String code) {
// 用户验证
Authentication authentication = null;
try {
MobileUserByOfficialAuthenticationToken officialAuthenticationToken =
new MobileUserByOfficialAuthenticationToken(code);
AuthenticationContextHolder.setContext(officialAuthenticationToken);
// 该方法会去调用MobileUserByOfficialDetailsServiceImpl.loadUserByUsername
authentication = authenticationManager.authenticate(officialAuthenticationToken);
} catch (Exception e) {
if (e instanceof BadCredentialsException) {
throw new UserPasswordNotMatchException();
} else {
throw new ServiceException(e.getMessage());
}
} finally {
AuthenticationContextHolder.clearContext();
}
MobileLoginUser mobileLoginUser = (MobileLoginUser) authentication.getPrincipal();
recordLoginInfo(mobileLoginUser.getUserId());
return tokenService.createToken(mobileLoginUser);
}
这里开始涉及到spring security,自定义一个MobileUserByOfficialAuthenticationToken ,用于authenticationManager找到合适的authenticationProvider来处理请求
/**
* @Description : 移动用户-公众号登录
* @Author : wzkris
* @Version : V1.0.0
* @Date : 2022/12/14 17:30
*/
public class MobileUserByOfficialAuthenticationToken extends AbstractAuthenticationToken { private final String code; /**
* Creates a token with the supplied array of authorities.
*/
public MobileUserByOfficialAuthenticationToken(String code) {
super(null);
this.code = code;
} /**
* @return 公众号授权需要的code
*/
public String getCode() {
return code;
} @Override
public Object getCredentials() {
return null;
} @Override
public Object getPrincipal() {
return null;
}
}
/**
* @Description : 公众号登录验证器
* @Author : wzkris
* @Version : V1.0.0
* @Date : 2022/12/14 17:33
*/
@Component
public class MobileUserByOfficialAuthenticationProvider implements AuthenticationProvider { @Resource(name = "mobileUserByOfficialDetailsServiceImpl")
private UserDetailsService userDetailsService; @Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
MobileUserByOfficialAuthenticationToken authenticationToken = (MobileUserByOfficialAuthenticationToken) authentication;
UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationToken.getCode());
//微信授权登录,无密码
return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
} @Override
public boolean supports(Class<?> authentication) {
return MobileUserByOfficialAuthenticationToken.class.equals(authentication);
}
}
下面的是具体请求微信拿到openId的方法
/**
* @Description : 微信公众号登录服务
* @Author : wzkris
* @Version : V1.0.0
* @Date : 2022/12/14 17:35
*/
@Service
public class MobileUserByOfficialDetailsServiceImpl implements UserDetailsService { @Resource
private RestTemplate restTemplate; @Resource
private MobileUserWechatService mobileUserWechatService; @Resource
private MobileUserService mobileUserService; @Resource
private ISysConfigService configService; @Resource
private WxOfficialService wxOfficialService; @Resource
private TransactionTemplate transactionTemplate; @Override
public UserDetails loadUserByUsername(String code) throws UsernameNotFoundException {
//获取请求token
OfficialAccessResult loginAccessToken = wxOfficialService.getLoginAccessToken(code);
//构造请求
String url = "https://api.weixin.qq.com/sns/userinfo" +
"?access_token=" + loginAccessToken.getAccessToken()
+ "&openid=" + loginAccessToken.getOpenId()
+ "&lang=zh_CN";
ResponseEntity<OfficialLoginResult> response = restTemplate.getForEntity(URI.create(url), OfficialLoginResult.class);
OfficialLoginResult loginResult = response.getBody();
//校验返回结果
Objects.requireNonNull(loginResult);
WxErrCodeUtils.checkResult(loginResult);
//业务逻辑
MobileUserWechat userWechat = mobileUserWechatService.queryByOpenId(loginResult.getOpenId());
//不为空则代表已经注册过,直接查询出来返回
if (ObjectUtils.isNotEmpty(userWechat)) {
MobileUser user = mobileUserService.getById(userWechat.getUserId());
return createLoginUser(user);
}
//否则就代表第一次登录,直接插入并且注册
String password = configService.selectConfigByKey("sys.user.initPassword"); MobileUser user = new MobileUser()
.setPassword(SecurityUtils.encryptPassword(password))
.setUsername(IdUtils.fastSimpleUUID())
.setNickname(loginResult.getNickname())
.setAvatar(loginResult.getHeadImgUrl())
.setSex(exchangeSex(loginResult.getSex()))
.setPhone(Constants.UNKNOWN);
//开启事务,保存用户和微信信息
transactionTemplate.execute(status -> {
mobileUserService.save(user);
mobileUserWechatService.save(new MobileUserWechat()
.setOpenId(loginAccessToken.getOpenId())
.setUnionId(loginAccessToken.getUnionId())
.setChannel(Constants.CHANNEL_OFFICIAL)
.setUserId(user.getId()));
return null;
});
return createLoginUser(user);
} private UserDetails createLoginUser(MobileUser user) {
return new MobileLoginUser(user, Constants.CHANNEL_OFFICIAL);
} /**
* @param sex 性别
* @return 微信性别转换成系统的性别
*/
private int exchangeSex(int sex) {
int real = sex - 1;
if (real < 0) {
return 2;
}
return real;
} }
微信公众号授权登录,整合spring security的更多相关文章
- 【tp5.1】微信公众号授权登录及获取信息录入数据库
微信公众号开发文档链接:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432 微信公众号授权登录分为两种: 1.以 ...
- 解决微信公众号授权登录和开放平台微信第三方应用授权登录获取到的用户Openid关联问题
开发背景: 最近一段时间一直在做关于微信方面的网站应用开发,这段时间也收获的不少关于微信开发方面的开发技能,接触的比较多的主要有微信公众号和微信网站app第三方登录授权,以及微信会员卡,优惠券和扫描二 ...
- uniapp - 微信公众号授权登录
[缘由] 采用uniapp进行微信小程序和微信公众号双版本开发:考虑到用户唯一性,我们后端确定了以“unionid”.作为唯一标识. 有的小伙伴估计也是刚入这坑,我就简单说一下步骤流程 [摸索] ...
- 微信公众号授权登录,提示“redirect_uri 参数错误”
做微信公众号开发授权登录的时候遇到的坑... 后台服务用node,index.js相关代码如下: const oauth = new OAuth(conf.appid, conf.appsecret) ...
- 微信公众号授权登录后报redirect_uri参数错误的问题
在进行微信公众号二次开发的时候,需要通过授权码模式来进行微信授权.比如,在进行登录的时候,用户点击了登录按钮,然后弹出一个授权框,用户点击同意后,就可以获取用户的OpenId等信息了.这篇文章主要 ...
- Chrome插件:微信公众号自动登录(chrome.extension)
manifest.json: { "manifest_version": 2, "name": "WX.AutoLogin", " ...
- 微信公众号授权,支付,退款总结【shoucang】
1.支付前准备 1.1首先两个平台接入账户. 商户平台:https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F 公众平台: ...
- PHP之路——微信公众号授权获取用户信息
官方文档链接:http://mp.weixin.qq.com/wiki/4/9ac2e7b1f1d22e9e57260f6553822520.html /** * 获取code */ public f ...
- 微信公众号授权回调用户信息,获取openid
1.--------------------用户授权登录并获取code 授权登录方式有两个,一种为静默授权登录(scope=snsapi_base),一种为非静默授权登录(scope=snsapi_u ...
- ASP.NET之MVC 微信公众号授权给第三方平台的技术实现流程(获取第三方平台access_token)
“出于安全考虑,在第三方平台创建审核通过后,微信服务器每隔10分钟会向第三方的消息接收地址推送一次component_verify_ticket,用于获取第三方平台接口调用凭据”.这是文档中的原话,也 ...
随机推荐
- apk签名之后安装失败
Android Studio 3.0.1 很奇怪的一个现象,直接run的话可以成功,debug也可以,但是用签名打包之后,却安装失败,原来是打包的时候选错了.原来签名时,Signature Versi ...
- Grafana + Prometheus 监控 Zookeeper
废话不多说,前几篇已经相应的介绍Grafana 跟 Prometheus,如有不清楚,请参考: https://www.cnblogs.com/zgz21/p/12054518.html https: ...
- 移动端性能测试--CPU资源
一.背景 在很多场景下我们去使用 App,可能会碰到手机会出现发热发烫的现象.这是因为 CPU 使用率过高.CPU 过于繁忙,会使得整个系统无法响应用户,整体性能降低,用户体验变得相当差,也容易引起 ...
- nginx的nginx.conf配置文件如何修改代理的路由
方法 location /api/ { set $request_uri_new $request_uri; if ($request_uri ~ "^/api/(.*)$") { ...
- 大规模人脸分类—allgather操作(2)
腾讯开源人脸识别训练代码TFace 中关于all_gather层的实现如下.接下来解释为什么backward要进行reduce相加操作. https://github.com/Tencent/TFac ...
- iOS底层原理02-alloc源码分析
首先,从最熟悉的入手 - 对象,看看这三个对象的内容,内存地址和指针地址. LGPerson *p1 = [LGPerson alloc]; LGPerson *p2 = [p1 init]; ...
- layui弹出层layer点击关闭还会显示在html中
我的弹出层是这样定义的: 它的属性为display:none <div id="divlayer" style="display:none"> &l ...
- 一个分布式websocket的实现
前情提要 之前我的项目里有一个合作编辑的功能,多个客户端的用户可以合作写一篇文章的不同部分,而且合作的任意作者互相还可以进行文字通讯.这种需求肯定是首选websocket了,因为服务器需要主动给客户端 ...
- ethcat开发记录 一
一.方案 1.移植开源方案SOEM 2.专用芯片 二.SOEM移植 (一)硬件 stm32f407,168M PHY:LAN8720A (ii) Points to note 1, the PHY a ...
- win7下MongoDB安装配置
之前看windows下安装MongoDB操作很是简单,今天在自己笔记本上安装一次,各种小问题.参照网上各大神帖子,再记录下个简单流程以便以后记得. 1.MongoDB官网上下载安装包 2.运行安装包, ...