一头扎进Shiro-自定义Realm

        一头扎进Shiro-集成Web之前的博客,我们都是用shiro.ini保存用户、角色、权限信息,本篇文章我们将这些信息保存到数据库,通过自定义Realm完成身份验证和权限验证。

  去掉用户、角色、权限信息,添加Realm信息的shiro.ini文件信息如下:

[main]
authc.loginUrl=/login
roles.unauthorizedUrl=/unauthorized.jsp
perms.unauthorizedUrl=/unauthorized.jsp
myRealm=com.tgb.realm.MyRealm
securityManager.realms=$myRealm
[urls]
/login=anon
/admin=authc
/student=roles[teacher]
/teacher=perms["user:create"]

  首先和大家展示下LoginServlet和MyRealm的代码实现,然后结合代码讲解下面的三种验证过程。

  LoginServlet:

package com.tgb.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;

public class LoginServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		System.out.println("login doget");
		req.getRequestDispatcher("login.jsp").forward(req, resp);
	}

	@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("errorInfo", "用户名或密码错误");
			req.getRequestDispatcher("login.jsp").forward(req, resp);
		}
	}

}
   MyRealm:

package com.tgb.realm;

import java.sql.Connection;
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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import com.tgb.dao.UserDao;
import com.tgb.entity.User;
import com.tgb.util.DbUtil;

public class MyRealm extends AuthorizingRealm {

	private UserDao userDao = new UserDao();
	private DbUtil dbUtil = new DbUtil();

	/**
	 * 为当前登录的用户授予权限
	 */
	@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.getRoles(con, userName));
			authorizationInfo.setStringPermissions(userDao.getPermissions(con,
					userName));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				dbUtil.closeCon(con);
			} catch (Exception e) {
			}
		}
		return authorizationInfo;
	}

	/**
	 * 验证当前登录的用户
	 */
	@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 authcInfo = new SimpleAuthenticationInfo(
						user.getUserName(), user.getPassword(), "xx");
				return authcInfo;
			} else {
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				dbUtil.closeCon(con);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return null;
	}
}

   success.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	welcome!
	<shiro:hasRole name="admin">
		welcome admin user!
	</shiro:hasRole>
	<shiro:hasPermission name="student:create">
		welcome student:create user!<shiro:principal/>
	</shiro:hasPermission>
</body>
</html>

   用户名不存在验证

   当我们在浏览器输入“http://localhost:8080/ShiroWeb/login”,使用不存在的用户名进行登录后,程序会进入到LoginServlet的subject.login(token)方法,F8执行过,会跳转到MyRealm的doGetAuthenticationInfo(AuthenticationToken token)方法进行身份验证,如果用户名不存在,则通过userDao.getByUserName返回的User实体为空,直接返回到login登录页。

   用户名存在、密码不正确验证

  如果我们在登录页输入的用户名正确、密码不正确,则在MyRealm的doGetAuthenticationInfo(AuthenticationToken token)方法中使用AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUserName(), user.getPassword(), "xx")方法,将用户输入保存在token中的用户名、密码和从数据库中查询出的用户名、密码进行比对,比对后发现密码不正确,直接返回到login登录页。

   用户名、密码正确验证

  如果我们在登录页输入的用户名、密码都正确,则在MyRealm中的doGetAuthenticationInfo(AuthenticationToken token)身份验证通过,继续在MyRealm的doGetAuthorizationInfo(PrincipalCollection principals)进行权限验证。
  通过authorizationInfo.setRoles(userDao.getRoles(con, userName))和authorizationInfo.setStringPermissions(userDao.getPermissions(con,userName))把根据当前用户名查询出当前用户的角色和权限信息保存到SimpleAuthorizationInfo对象中。
  这样shiro框架便可以根据SimpleAuthorizationInfo对象中的信息判断success.jsp页面中的哪些shiro标签内容可以显示。
  通过上述验证过程我们可以发现,shiro更多的是帮助我们完成验证过程。我们需要从数据库查询当前用户的角色、权限,把这些信息告诉shiro框架,同时在jsp页面定义好哪些内容哪些角色哪些权限可以访问,剩下的就是shiro框架的事儿了。
  shiro是不是很简单?
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值