单realm实现shiro手机验证码登录

5 篇文章 0 订阅
3 篇文章 0 订阅

上一篇文章写的是shiro实现手机验证码登录:http://blog.csdn.net/modjie/article/details/79221774    用了多realm的方式,需要自定义token等多个类,实现过程复杂,并且还存在一个问题:密码错误异常UnknownAccountException和用户不存在异常IncorrectCredentialsException捕获出错了,初步猜测是由于realm的验证源码中没有将异常抛出,导致其他realm的异常覆盖了原来的异常,但还未解决,由于本人水平和时间有限,暂时就不去解决了。同时发现这种方法来实现手机验证码的登录实在是太笨太麻烦了。接下来分享一下单realm实现手机验证码登录。

1、在常规的用户名密码登录时,我们会自定义一个realm,在这个realm中加入以下逻辑判断就可以实现了。代码如下

package com.java.travel.realm;

import javax.annotation.Resource;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import com.java.travel.entity.ExUser;
import com.java.travel.service.ExUserService;

public class UserNamePasswordRealm extends AuthorizingRealm {

	@Resource
	ExUserService exUserService;

	/**
	 * 为当限前登录的用户授予角色和权限
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * 验证当前登录的用户
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//接收输入的用户名
		String nickName = (String) token.getPrincipal();	
		//查看UsernamePasswordToken可知,getCredentials()方法的返回值是char []类型的,所以不能直接转化成string。
		char [] ch = (char[]) token.getCredentials();
		//接收输入的密码
		String password = new String(ch);		
		ExUser exUser;
		// 如果用户名长度为11位,则假设是电话号码,去数据库查询,如果查询不到则返回null。
		//如果昵称长度大于11,则表示输入非法,返回null,
		//如果查询到了,则判断接收的密码,如果为验证码则表示验证码登录,否则就是普通登录,则传入正确的密码进行验证
		if (nickName.length() == 11) {
			exUser = exUserService.selectByTelphoneNum(nickName);
			if (exUser != null) {
				//这里要注意,如果是验证码登录是不需要密码的,因此在控制器中创建token实例时,第二个参数传任意字符串即可,
				//然后在这里判断。为了保险起见,我传的是中文的验证码,因为前台输入密码是不能输入中文的。
				if (password.equals("验证码")) {
					password="验证码";
				}else  {
					password=exUser.getPASSWORD();
				}
				AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(exUser.getTEL(), password,"xx");
				return authcInfo;
			}else {
				return null;
			}
		} else if (nickName.length() > 11) {
			return null;
		} else {
			exUser = exUserService.selectByNickName(nickName);	
			if (exUser != null) {
				AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(exUser.getNICKNAME(), exUser.getPASSWORD(),
						"xx");
				return authcInfo;
			}
			else {
				return null;
			}
		}
	}

}
2、注释解释的很清楚,这里就不做说明了,接下来是控制器的代码。用户名密码登录代码如下:

/**
	 * 登录
	 * @param nickName
	 * @param password
	 * @return
	 */
	@RequestMapping(value = "login", method = RequestMethod.GET)
	@ResponseBody
	public int login(String nickName, String password) {
		Subject subject = SecurityUtils.getSubject();		
		UsernamePasswordToken token = new UsernamePasswordToken(nickName, password);
		try {
			subject.login(token);
			return 1;
		} catch (UnknownAccountException ex) {// 用户名没有找到。
			return -1;
		} catch (IncorrectCredentialsException ex) {// 用户名密码不匹配。
			return -2;
		} catch (AuthenticationException e) {//其他异常
            return -3;
        }
	}

3、前端ajax登录请求

// 登录ajax请求
function loginAjax() {
	var nickName = $(".account").val();
	var password = $(".password").val();
	if (nickName == "") {
		shakeModal("账号不能为空");
	} else if (password == "") {
		shakeModal("密码不能为空");
	} else {
		$.ajax({
			type : "get",
			url : "login",
			data : {
				nickName : nickName,
				password : password
			},
			dataType : "json",
			success : function(data) {
				if (data == 1) {
					alert("登录成功1");
				} else if (data == -1) {
					shakeModal("账号不存在");
				} else if (data == -2) {
					shakeModal("密码错误");
				} else {
					shakeModal("未知错误,请刷新页面重新登录");
				}
			}
		});
	}

}


如果是验证码登录的话,只需要将ajax方法中的password改成“验证码”或其他任意字符就可以了,但是要注意,这里传的是什么字符,在token中对password进行判断时也要填什么字符,这里只是简单说明,有需要的朋友可以参考一下,根据自己的需求做改动,本人水平有限,不喜勿喷。



  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值