shiro_07_自定义Realm

在之前我们用的都是直接读取ini文件的数据,显然这种方式不现实,仅针对数据量较小的时候的测试,这一篇来介绍利用自定义的Realm读取数据库的数据。

第一步,根据用户拥有角色和权限建立数据库:

我们按照上一篇的用户关系来建数据库,一个角色可以对应多个用户,一个角色也可以对应多个权限。所以我们要建3张表:

t_user(id,userName,password,roleId)

t_roles(id,roleName)

t_permission(id,permission,roleId)

每个用户对应一个roleId外键,关联t_role表,这样就实现了一个角色对应多个用户,每一个权限对应一个roleId外键,关联t_role表,这样实现了一个角色对应多个权限。

按照之前的数据填好表。

第二步:自定义Realm

新建MyRealm类,继承AuthorizingRealm,实现里面的doGetAuthenticationInfo,doGetAuthorizationInfo方法,

首先实现doGetAuthenticationInfo方法:获取token里面的用户名,然后去数据库找看是否有这一个用户名,如果没有直接抛出异常,如果有,会new 一个SimpleAuthenticationInfo对象将从数据库找到的用户名和密码传进去,看是否和token里面的密码一样,如果不一样,也会抛出异常,如果一样则身份验证通过,

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String userName= (String)token.getPrincipal();//获取身份信息
		//根据用户名查找
		Connection con = null;
		try {
			con = dbUtil.getCon();
			User user = userDao.getByUserName(con, userName);
			if(user!=null) {
				AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"xx");
				return authenticationInfo;
			}
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
		
	}

然后调用doGetAuthorizationInfo方法去把拥有的权限和角色获取到,通过用户名从数据库里找到角色和权限分别存储在set集合里,new 一个authorizationInfo对象,调用setRoles和setStringPermissions方法将从数据库里获得的set集合放入,返回authorizationInfo即可。

	/**
	 * 对已经身份认证过的用户授予权限
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		String userName = (String)principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		Connection con = null;
		try {
			con = dbUtil.getCon();
			authorizationInfo.setRoles(userDao.getRole(con,userName));
			authorizationInfo.setStringPermissions(userDao.getPermissions(con,userName));
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return authorizationInfo;
	}

数据库的操作就不一一说明了,很简单。

第三步:配置ini文件:

[main]
authc.loginUrl=/login
roles.unauthorizedUrl=/unauthorized.jsp
perms.unauthorizedUrl=unpermitted.jsp
MyRealm=com.java.realm.MyRealm
securityManager.realm=$MyRealm
[urls]
/login=anon
/admin=authc
/student=roles[teacher]
/delete=perms["user:delete"]

把用户,角色,权限信息去掉,然后换成自定义的realm。

第四步:测试。

没有问题。

分析一遍执行过程:

首先,从登录界面开始说,用户输入用户名和密码,点击登录,请求/login请求,从web.xml中找到对应映射的servlet类,找到了LoginServlet,执行里面的dopost方法,这个方法将用户输入的用户名和密码获取,并利用shiro得到当前用户subject,并将用户名密码封装成一个token,当subject当前用户执行.login方法时,把token带着就执行刚才写的doGetAuthenticationInfo方法,进行身份验证,具体验证过程上面已经介绍了,当身份验证通过后,有调用doGetAuthorizationInfo方法进行角色和权限的授权,并进行角色和权限的验证,执行完login ,接着执行我们自己写的转发到sueecss界面。当登录后,用户再请求时,shiro会再进行一遍角色和权限的授权,并再进行一次角色和权限的验证,因此说shiro安全性很高。

loginServlet的dopost方法:

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("login dopost");
		String userName = req.getParameter("userName");
		String password = req.getParameter("password");
		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
		try {
			subject.login(token);
			resp.sendRedirect("success.jsp");
		}catch(Exception e) {
			e.printStackTrace();
			req.setAttribute("errorMsg", "用户名或密码错误");
			req.getRequestDispatcher("login.jsp").forward(req, resp);
		}
	}
	

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值