shiro怎么样才能成功登录?

gccd 发布于 2013/05/12 20:31
阅读 15K+
收藏 0

在实践shiro来实现权限时,遇到一些问题.很不解.

我模仿springside的配置,但是 写一个ShiroDbRealm 继承AuthorizingRealm时,

doGetAuthenticationInfo总是没能成功登录.我怀疑是数据库问题.但是不知道怎么入手修改.

Controller代码

@RequestMapping(value = "/login", method = RequestMethod.POST)
	public String login(String username, String password, Model model) {
		// model.addAttribute(FormAuthenticationFilter.DEFAULT_USERNAME_PARAM,
		// userName);
		UsernamePasswordToken token = new UsernamePasswordToken(username,
				password);
		token.setRememberMe(true);
		Subject currentUser = SecurityUtils.getSubject();
		try {
			currentUser.login(token);//不明白的是他怎么匹配密码的?我没告诉他那个是正确的password,那个是username.
		} catch (UnknownAccountException uae) {
			System.out.println("账户不存在!");
		} catch (IncorrectCredentialsException ice) {
			System.out.println("密码不正确!");
		} catch (LockedAccountException lae) {
			System.out.println("账户被禁了!");
		} catch (AuthenticationException ae) {
			System.out.println("认证错误!");
		}
		return "index";
	}

错误如下


这个是数据库表 t_staff

public class ShiroDbRealm extends AuthorizingRealm{

	protected AccountService accountService;
	@Autowired
	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}
	/**
	 *授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
		Staff staff = accountService.findUserByLoginName(shiroUser.loginName);
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		for (Role role : staff.getRoles()) {
			//基于Role的权限信息
			info.addRole(role.getName());
			//基于Permission的权限信息
			info.addStringPermissions(role.getPermissionList());
		}
		return info;
	}
	
	/**
	 * 登录时调用
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		Staff staff=null;
		staff = accountService.findUserByLoginName(token.getUsername());
		System.out.println("username"+token.getUsername());
		System.out.println("password"+new String(token.getPassword()));
		if (staff != null) {
			if (staff.getStatus().equals("disabled")) {
				throw new DisabledAccountException();
			}

//			byte[] salt = Encodes.decodeHex(staff.getSalt());
			return new SimpleAuthenticationInfo(
					new ShiroUser(staff.getLoginname(), staff.getName()),
					staff.getPassword(),
//					ByteSource.Util.bytes(salt),
					getName());
		} else {
			return null;
		}
	}
}
shiro关键配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
	default-lazy-init="true">

	<description>Shiro安全配置</description>
   
	<!-- Shiro's main business-tier object for web-enabled applications -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="shiroDbRealm" />
		<property name="cacheManager" ref="shiroEhcacheManager" />
	</bean>

	<!-- 項目自定义的Realm -->
	<bean id="shiroDbRealm" class="scau.mis.sexyone.service.member.impl.ShiroDbRealm" depends-on="staffDao,roleDao">
		<property name="accountService" ref="accountService"/>
	</bean>
	
	<!-- Shiro Filter -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<property name="loginUrl" value="/login" />
		<property name="successUrl" value="/" />
		<property name="filterChainDefinitions">
			<value>
				/logout = logout
				/account/** = user
				/** = authc
			</value>
		</property>
	</bean>

	<!-- 用户授权信息Cache, 采用EhCache -->
	<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
		<property name="cacheManagerConfigFile" value="classpath:security/ehcache-shiro.xml"/>
	</bean>
	
	<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
	
	<!-- AOP式方法级权限检查  -->
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
		<property name="proxyTargetClass" value="true" />
	</bean>
	<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    	<property name="securityManager" ref="securityManager"/>
	</bean>
</beans>

加载中
1
ajavaloser
ajavaloser

哪个版本的,从我看到的最新版情况来看,
 login controller里的post是处理登陆失败的情况,ShiroDbRealm里才是真正验证的地方,两个都在做同一件事的话,是不是多余了,且造成了不可预料的问题。另外你用的SimpleAuthenticationInfo构造函数,想去掉密码hash,是否成功,springside里在ShiroDbRealm中重写了initCredentialsMatcher来匹配sha-1,要是明文,你去掉这段没有,如果没去肯定有问题。看你sql结果是查到了用户,问题应该就在密码上

OSC屠夫
OSC屠夫
@ajavaloser 多谢了
ajavaloser
ajavaloser
回复 @xForMe : 数据库里的密码是加过密的,加了密,就算你能进入数据库,也很难破解密码
OSC屠夫
OSC屠夫
我想问下,这个从那边知道密码的
ajavaloser
ajavaloser
回复 @陈广成 : 不用谢,多看看springside在github上的wiki吧,以及springside里面的注释,这些都花了 @江南布衣 很多心血
gccd
gccd
谢谢你,果然是重写的原因.
0
F_L_F
F_L_F
UsernamePasswordToken token = new UsernamePasswordToken(username,
				password);

这个不是已经带了帐号、密码信息了么!

执行到

currentUser.login(token);
就会调用 ShiroDbRealm的 doGetAuthenticationInfo方法。

但是我看你accountService.findUserByLoginName(token.getUsername());这个service只传入了username,没有传password,写错了吧?是不是应该是accountService.findUserByLoginName(token.getUsername(),token.getPassword())????

gccd
gccd
谢谢~!
0
gccd
gccd

引用来自“ajavaloser”的答案

哪个版本的,从我看到的最新版情况来看,
 login controller里的post是处理登陆失败的情况,ShiroDbRealm里才是真正验证的地方,两个都在做同一件事的话,是不是多余了,且造成了不可预料的问题。另外你用的SimpleAuthenticationInfo构造函数,想去掉密码hash,是否成功,springside里在ShiroDbRealm中重写了initCredentialsMatcher来匹配sha-1,要是明文,你去掉这段没有,如果没去肯定有问题。看你sql结果是查到了用户,问题应该就在密码上

0
zeewane
zeewane
是通过HashedCredentialsMatcher这个类来进行token与info的匹配的,不匹配就抛出incorrect异常
返回顶部
顶部