shiro SecurityUtils.getSubject().getPrincipal()得到null 的解决方法
1 问题的由来
自定义的Realm 继承 AuthorizingRealm ,本想在doGetAuthenticationInfo 认证方法中通过Object o = SecurityUtils.getSubject().getPrincipal() 得到前端传来的信息的,然后通过instanceof 判断 o 的到底是什么类,来判断到底是用户登录还是管理员登录。
结果发现SecurityUtils.getSubject().getPrincipal() 得到的是null
2 解决方法
采用装饰类的思路解决
由于 Controller 层中 subject.login(authenticationToken); 登录的时候传递给Shiro的类是UsernamePasswordToken 类,该类对象会原封不动作为 token 传递到 doGetAuthenticationInfo 方法里。既然如此就可以将 UsernamePasswordToken 类进行装饰,然后给它加一个新的成员变量传递我想传递的信息,这样在 doGetAuthenticationInfo 方法中就可以获取到了。
装饰类源码如下:
package com.wu.demoblog.decorate;
import lombok.Data;
import org.apache.shiro.authc.UsernamePasswordToken;
/**
* UsernamePasswordToken 的装饰类,为它添加一些东西后再使用
* @Author :吴用
* @Date :2020-08-14 22:19
* @Version :1.0
*/
@Data
public class UsernamePasswordTokenChild extends UsernamePasswordToken {
private Object msg; //这里是新加的成员变量
// 注意构造方法是不继承的,所以需要自己写一下,用 idea 可以快速构建下面这些构造方法
public UsernamePasswordTokenChild() {
super();
}
public UsernamePasswordTokenChild(String username, char[] password) {
super(username, password);
}
public UsernamePasswordTokenChild(String username, String password) {
super(username, password);
}
public UsernamePasswordTokenChild(String username, char[] password, String host) {
super(username, password, host);
}
public UsernamePasswordTokenChild(String username, String password, String host) {
super(username, password, host);
}
public UsernamePasswordTokenChild(String username, char[] password, boolean rememberMe) {
super(username, password, rememberMe);
}
public UsernamePasswordTokenChild(String username, String password, boolean rememberMe) {
super(username, password, rememberMe);
}
public UsernamePasswordTokenChild(String username, char[] password, boolean rememberMe, String host) {
super(username, password, rememberMe, host);
}
public UsernamePasswordTokenChild(String username, String password, boolean rememberMe, String host) {
super(username, password, rememberMe, host);
}
}
在 Controller 层使用该对象,把自己想要的信息放进该对象中,在 Realm 中将 token 强转成该类对象,然后就可以通过 getMsg() 方法提取出来自己在Controller层放入的内容了。