PC端网站-微信扫码登录+shiro权限框架免密登录

文章原创,转载请注明原文链接

一、准备工作:

1. 一个认证的微信《开放平台》账号。

PC端网站-微信扫码登录+shiro权限框架免密登录_第1张图片

2. 在这个账号下添加网站【已审核通过的网站应用】。

PC端网站-微信扫码登录+shiro权限框架免密登录_第2张图片

3.一个测试用的域名。我测试的时候是在腾讯云买的,1¥/月,只需要实名认证,不需要备案。这个域名只能本机使用。

PC端网站-微信扫码登录+shiro权限框架免密登录_第3张图片

备注:账号认证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。当配置好网站应用时可得到这两个参数。

PC端网站-微信扫码登录+shiro权限框架免密登录_第4张图片

 

我使用的是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);

​

文章原创,转载请注明原文链接

你可能感兴趣的:(PC端网站-微信扫码登录+shiro权限框架免密登录)