shiro 不管登录成功还是失败都出现这个bug

28 回复

package com.coracle.fast.service.impl.shiro;

import org.apache.shiro.authc.AuthenticationException;

import org.apache.shiro.authc.AuthenticationInfo;

import org.apache.shiro.authc.AuthenticationToken;

import org.apache.shiro.authc.LockedAccountException;

import org.apache.shiro.authc.SimpleAuthenticationInfo;

import org.apache.shiro.authc.UsernamePasswordToken;

import org.apache.shiro.authz.AuthorizationException;

import org.apache.shiro.authz.AuthorizationInfo;

import org.apache.shiro.authz.SimpleAuthorizationInfo;

import org.apache.shiro.realm.AuthorizingRealm;

import org.apache.shiro.subject.PrincipalCollection;

import org.apache.shiro.util.ByteSource;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

import com.coracle.fast.entity.shiro.Permission;

import com.coracle.fast.entity.shiro.Role;

import com.coracle.fast.entity.shiro.User;

import com.coracle.fast.service.UserService;

@Service(“shiroRealm”)

@Transactional(readOnly = true)

public class ShiroRealm extends AuthorizingRealm {

@Autowired

private UserService userService;

/**

* 权限认证

*/

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

if (principalCollection == null) {

throw new AuthorizationException(“PrincipalCollection method argument cannot be null.”);

}

// 获取登录时输入的用户名

String loginName = (String) principalCollection.fromRealm(getName()).iterator().next();

// 到数据库查是否有此对象

User user = userService.findByUserName(loginName);

if (null == user) {

return null;

}

if (user.isLocked()) {

throw new LockedAccountException(“Account [” + user.getUserName() + “] is locked.”);

}

// 权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)

SimpleAuthorizationInfo auth = new SimpleAuthorizationInfo();

if (user.getRoles() != null) {

for (Role role : user.getRoles()) {

auth.addRole(role.getName());

if (role.getPermissions() != null) {

for (Permission p : role.getPermissions()) {

auth.addStringPermission(p.getName());

}

}

}

}

if (user.getPermissions() != null) {

for (Permission p : user.getPermissions()) {

auth.addStringPermission(p.getName());

}

}

return auth;

}

/**

* 登录认证;

*/

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)

throws AuthenticationException {

// UsernamePasswordToken对象用来存放提交的登录信息

UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

// 查出是否有此用户

User user = userService.findByUserName(token.getUsername());

if (user != null) {

// 若存在,将此用户存放到登录认证info中

// 用户名 密码 slat realm name

return new SimpleAuthenticationInfo(user.getUserName(), user.getPassword(),

ByteSource.Util.bytes(user.getSalt()), getName());

}

return null;

}

}

@wendal 不反null 返回什么 ?

并且登录成功 也不是返回null

throw new UnknownAccountException();

debug 了一个 发现执行顺序是这样的

/**

* 认证回调函数,登录时调用.

* 登录认证;

*/

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)

throws AuthenticationException {

// UsernamePasswordToken对象用来存放提交的登录信息

UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

// 查出是否有此用户

User user = userService.findByUserName(token.getUsername());

if (user != null) {

// 若存在,将此用户存放到登录认证info中

// 用户名 密码 slat realm name

return new SimpleAuthenticationInfo(user.getUserName(), user.getPassword(),

ByteSource.Util.bytes(user.getSalt()), getName());

}else{

throw new UnknownAccountException();

}

}

1、执行 User user = userService.findByUserName(token.getUsername());

发现 user 是 null

2、 throw new UnknownAccountException();

然后没跳出方法,反而 有执行了 一边 User user = userService.findByUserName(token.getUsername());

这个时候 发现 user 不是null

但是有由于密码错误

抛出 IncorrectCredentialsException

这样就导致了 不管登录成功还是失败 都出现了 上面的 bug

没跳出方法 抛异常还能没跳出方法

是的 ,

第一次 User user = userService.findByUserName(token.getUsername()); user 是null (数据库有数据)

就执行了

throw new UnknownAccountException();

这时候 程序又执行了 一遍 User user = userService.findByUserName(token.getUsername()); user 这时候不是null 了

登录成功后 doGetAuthorizationInfo 方法也没执行

第一次为null, 这必须先查清楚

User user = userService.findByUserName(token.getUsername()); // user 是null (数据库有数据)

打印 token.getUsername()的值出来

log.debug(“name=[”+token.getUsername()+“]”);

发现是 点击 submit后

没有到controller,现在执行了

User user = userService.findByUserName(token.getUsername()); // user 是null (数据库有数据)

这时候 getUsername 是 null

抛出异常,

执行了 controller

执行 User user = userService.findByUserName(token.getUsername());

这个时候 getUsername 是 页面的 admin

密码错误,跳出。

这是同一个req 那就检查第一个token是哪里冒出的

通一个 req

仅仅点击了 一次 提交

怎么检查 这个token呢,?

发现 第一个 进来的时候 password 是 页面的值 但是 username是null

然后又进来了一个 这时候 username和password 都是页面的值

去debug这个token类的构造方法,看它是哪里创建的,创建了多少次

@wendal 在没有进入 controller之前 在 FormAuthenticationFilter 里的 excutelogin 产生的 token

不是总共构建了2个token对象吗?我要知道这两个对象是哪里的java代码new出来的

不过,基本上确定是shiro.ini 重复拦截了,需要把第一个token干掉

@wendal

第一个 token

public abstract class AuthenticatingFilter extends AuthenticationFilter {

public static final String PERMISSIVE = “permissive”;

//TODO - complete JavaDoc

protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {

AuthenticationToken token = createToken(request, response);

if (token == null) {

String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " +

“must be created in order to execute a login attempt.”;

throw new IllegalStateException(msg);

}

try {

Subject subject = getSubject(request, response);

subject.login(token);

return onLoginSuccess(token, subject, request, response);

} catch (AuthenticationException e) {

return onLoginFailure(token, e, request, response);

}

}

这里 AuthenticationToken token = createToken(request, response);

产出来的

这个 过滤 AuthenticationFilter

不知哪里出来的

@javanan shiro.ini里面配置的咯,贴

那另外一个token呢?

这个类的

public class ModularRealmAuthenticator extends AbstractAuthenticator

这里

protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) {

if (!realm.supports(token)) {

String msg = “Realm [” + realm + “] does not support authentication token [” +

token + "]. Please ensure that the appropriate Realm implementation is " +

“configured correctly or that the realm accepts AuthenticationTokens of this type.”;

throw new UnsupportedTokenException(msg);

}

AuthenticationInfo info = realm.getAuthenticationInfo(token);

if (info == null) {

String msg = “Realm [” + realm + "] was unable to find account data for the " +

“submitted AuthenticationToken [” + token + “].”;

throw new UnknownAccountException(msg);

}

return info;

}

@wendal

在自己的

controller

里 传过去的

SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUserName(), user.getPassword()));

登录操作是控制器里面主动login,但shiro filter又做了匹配

所以,现在要解决的就是把第一个token干掉,也就是shiro.ini里面的匹配去掉

@wendal

哦 原来是这样,, 那么直接用 shiro的 登录就好了。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值