博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一头扎进Shiro-自定义Realm
阅读量:3978 次
发布时间:2019-05-24

本文共 5051 字,大约阅读时间需要 16 分钟。

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

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

[main]authc.loginUrl=/loginroles.unauthorizedUrl=/unauthorized.jspperms.unauthorizedUrl=/unauthorized.jspmyRealm=com.tgb.realm.MyRealmsecurityManager.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"%>
Insert title here welcome!
welcome admin user!
welcome student:create user!

   用户名不存在验证

   当我们在浏览器输入“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是不是很简单?

转载地址:http://cokui.baihongyu.com/

你可能感兴趣的文章
P8-c++对象和类-01默认构造函数详解
查看>>
P1-c++函数详解-01函数的默认参数
查看>>
P3-c++函数详解-03函数模板详细介绍
查看>>
P4-c++函数详解-04函数重载,函数模板和函数模板重载,编译器选择使用哪个函数版本?
查看>>
P5-c++内存模型和名称空间-01头文件相关
查看>>
P6-c++内存模型和名称空间-02存储连续性、作用域和链接性
查看>>
P9-c++对象和类-02构造函数和析构函数总结
查看>>
P10-c++对象和类-03this指针详细介绍,详细的例子演示
查看>>
ksh 命令分隔符
查看>>
sed 精萃
查看>>
awk 精萃
查看>>
awk 注释
查看>>
GROUPING SETS、ROLLUP、CUBE
查看>>
数据类型和变量
查看>>
表连接(JOIN)
查看>>
游标(Cursor)
查看>>
复合语句(compound statement)
查看>>
DB2 物化查询表
查看>>
IF 语句
查看>>
循环语句
查看>>