文章原创,转载请注明原文链接
一、准备工作:
1. 一个认证的微信《开放平台》账号。
2. 在这个账号下添加网站【已审核通过的网站应用】。
3.一个测试用的域名。我测试的时候是在腾讯云买的,1¥/月,只需要实名认证,不需要备案。这个域名只能本机使用。
备注:账号认证and网站认证都需要公司提供,需要软妹币和公司的章子。
二、调微信接口:
微信官方文档即可。https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=733b43ce86585debf2012bcf0f1c3d429094f3fe&lang=zh_CN。
微信扫码的顺序是:生成二维码-》用户确认-》跳转url,携带code-》用code换openId-》获取用户信息(unionid,nickname)
微信接口的准备参数:AppID和AppSecret。当配置好网站应用时可得到这两个参数。
我使用的是js嵌码的方式。通过实例化WxLogin对象,会在页面初始化的时候获取到code和随机数state,然后执行回调url,跳转到redirect_uri页面。【redirect_uri必须是域名访问,且域名必须是网站应用配置的域名】。
页面获取到code,传到后端接口中。接口通过code换取用户的唯一标识。openId,access_token。进一步获取微信用户的unionid,nickname,之类的用户信息。
接口的调用没什么可说的。繁琐的是前期的准备工作。
接下来获取到用户信息(唯一标识等)。后端可以判断此用户存不存在,好进行之后的操作,如果是系统有效用户,则需要通过shiro登录验证。
shiro登录验证:(账号密码登录)
boolean rememberMe = false;
String host = StringUtils.getRemoteAddr((HttpServletRequest)request);
String captcha ="";
boolean mobile = false;
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password.toCharArray(),
rememberMe, host, captcha, mobile);
subject.login(token);
UsernamePasswordToken 是继承自org.apache.shiro.authc.UsernamePasswordToken(shiro的账号密码令牌)
最重要的是subject.login(token),登录验证。想要免密登录需要两步:
1、需要一个没有密码的token
2、在登录验证的时候跳过密码验证。
首先第一步:
因为代码原有的UsernamePasswordToken,所以只需要新增一个无密码的构造方法。再新加一个属性,用来密码校验的时候判断这是免密登录。
/**
* 用户和密码(包含验证码)令牌类
*/
public class UsernamePasswordToken extends org.apache.shiro.authc.UsernamePasswordToken {
private static final long serialVersionUID = 1L;
private String captcha;
private boolean mobileLogin;
private String loginType; //登录方式 微信
public UsernamePasswordToken() {
super();
}
/**
* 账号密码登录
*/
public UsernamePasswordToken(String username, char[] password,
boolean rememberMe, String host, String captcha, boolean mobileLogin) {
super(username, password, rememberMe, host);
this.captcha = captcha;
this.mobileLogin = mobileLogin;
this.loginType = DictCodes.LOGIN_TYPE_PC;
}
public UsernamePasswordToken(String username) {
super(username, "", false, null);
this.loginType = DictCodes.LOGIN_TYPE_WECHAT;
}
public String getCaptcha() {
return captcha;
}
public void setCaptcha(String captcha) {
this.captcha = captcha;
}
public boolean isMobileLogin() {
return mobileLogin;
}
public String getLoginType() {
return loginType;
}
public void setLoginType(String loginType) {
this.loginType = loginType;
}
}
静态变量就是标识,自己定义即可。
第二步:
想要跳过密码校验,需要重写shiro的密码校验方法。
首先找到shiro的密码校验方法:
org.apache.shiro.authc.credential.HashedCredentialsMatcher.doCredentialsMatch()
【shiro代码,jar包】
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
Object tokenHashedCredentials = this.hashProvidedCredentials(token, info);
Object accountCredentials = this.getCredentials(info);
return this.equals(tokenHashedCredentials, accountCredentials);
}
我们继承这个类,并重写doCredentialsMatch()
public class MyHashedCredentialsMatcher extends HashedCredentialsMatcher {
public MyHashedCredentialsMatcher() {
}
public MyHashedCredentialsMatcher(String hashAlgorithmName) {
super(hashAlgorithmName);
}
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
UsernamePasswordToken uToken = (UsernamePasswordToken) token;
if (uToken.getLoginType().equals(DictCodes.LOGIN_TYPE_PC)) {
return super.doCredentialsMatch(token, info);
} else {
return true;
}
}
}
在自定义密码校验规则处,将对象实例化或强转为我们免密的类MyHashedCredentialsMatcher【这部分代码不可复用】
/**
* 设定密码校验的Hash算法与迭代次数
*/
@PostConstruct
public void initCredentialsMatcher() {
MyHashedCredentialsMatcher matcher = new MyHashedCredentialsMatcher(SystemService.HASH_ALGORITHM);
matcher.setHashIterations(SystemService.HASH_INTERATIONS);
setCredentialsMatcher(matcher);
}
免密登录就配置好了。
这部分代码是建立在完善的shiro框架,账号密码登录已投入使用的基础上进行免密登录。若想搭建shiro请参考其他文档。
shiro登录验证:(无密码登录)
Subject subject = SecurityUtils.getSubject();
// 免密登录
UsernamePasswordToken token = new UsernamePasswordToken(username);
subject.login(token);
文章原创,转载请注明原文链接