简单说一下思路
1.用户第一次登录/绑定,通过微信的code拿到用户的
openid
,存到数据库里
2.用户第二次请求,发起一个微信自动登录请求,同样传入微信的code,后台检验获取openid,检验该openid是否已经存在数据库,如果有就可以自动登录.
3.实现一个自己的MyRealm
和MyOpenIdToken
,主要为了能够Subject存入openid方便检验
//通过获取到自动登录的openId
String openid = apiResult.get("openid");
Subject subject = SecurityUtils.getSubject();
//使用自定义realm验证openid是否已绑定用户
WxOpenIdToken wxOpenIdToken =new WxOpenIdToken(openid);
subject.login(wxOpenIdToken);`
,
`MyOpenIdToken`:类似实体类,需要继承`UsernamePasswordToken`
`MyRealm`:继承`AuthorizingRealm` 真正的验证逻辑在这里处理,
注意 :多个realm需要在shiro配置中配置使用策略,也可以自行百度
缺点:因为subject中存的是openId所以登录之后还需要额外的去获取用户信息
贴一下我的代码
MyOpenIdToken.java
//MyOpenIdToken
public class WxOpenIdToken extends UsernamePasswordToken implements Serializable {
private String openId;
/**
*
*/
private static final long serialVersionUID = 4812793519945855483L;
@Override
public Object getPrincipal() {
return getOpenId();
}
@Override
public Object getCredentials() {
return "ok";
}
public WxOpenIdToken(String openId){
this.openId=openId;
}
}
WxOpenIdRealm.java
public class WxOpenIdRealm extends AuthorizingRealm {
@Resource
private SysUserDao sysUserDao;
@Resource
private SysMenuDao sysMenuDao;
/**
* 授权
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//TODO 用户权限列表,普通信息等...
return info;
}
/**
* 鉴权 openid 判断是否用户是否已经绑定微信
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String openid = (String) token.getPrincipal();
//sysUserDao.getbyWxaOpenId 根据openid查询是否有已绑定的userid,有就时已绑定
SysUserEntity exUser = sysUserDao.getbyWxaOpenId(openid);
if (exUser != null) {
AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(openid, "ok", this.getClass().getSimpleName());
return authcInfo;
} else {
return null;
}
}
}
ShiroConfig.java 注入两个realm并设置验证策略
@Bean
public UserRealm userRealm(){
UserRealm userRealm = new UserRealm();
//账号密码登录使用realm
return userRealm;
}
@Bean
public WxOpenIdRealm wxCodeRealm(){
WxOpenIdRealm wxOpenIdRealm = new WxOpenIdRealm();
//小程序使用openid登录使用的realm
return wxOpenIdRealm;
}
/**
* 系统自带的Realm管理,主要针对多realm
* */
@Bean
public ModularRealmAuthenticator modularRealmAuthenticator() {
ModularRealmAuthenticator modularRealmAuthenticator = new ModularRealmAuthenticator();
//只要有一个成功就视为登录成功
modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return modularRealmAuthenticator;
}