老蝴蝶提醒,在学习这一章节之前,一定要学习前面的章节及RBAC教程部分。
一. Servlet 整合 Shiro 实现 RBAC准备
一.一 数据库准备
数据库与上一章节一致, user 表里面添加了盐,并且更新了密码, 同时 相对应的pojo也进行了更新。
相对应的 rbac.sql 文件会更新到链接里面。
一.二 前端页面准备
前端页面采用 RBAC系列中的页面,与前面的实现一致。
二. Servlet 整合 Shiro 实现 RBAC
二.一 添加 pom.xml 依赖
包括 servlet, shiro,数据库,日志,json转换等常用依赖。
<dependencies> <!--tomcat中 jsp与 servlet依赖 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!-- jstl 与 standard 依赖--> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.1</version> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.2</version> </dependency> <!-- mysql依赖 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency> <!-- c3p0依赖 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> </dependencies> <build> <plugins> <!-- 编译的jdk版本 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <!--tomcat的插件名, tomcat7-maven-plugin, 用的是tomcat7版本 --> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <!--tomcat的端口号 --> <path>/Shiro_Servlet</path> <!--tomcat的项目名 --> <uriEncoding>UTF-8</uriEncoding> <!-- 防止get 提交时乱码 --> </configuration> </plugin> </plugins> </build>
二.二 web.xml 添加配置
<!-- 配置监听器 --> <listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener> <context-param> <param-name>shiroEnvironmentClass</param-name> <param-value>org.apache.shiro.web.env.IniWebEnvironment</param-value> </context-param> <!-- 配置文件的路径 --> <context-param> <param-name>shiroConfigLocations</param-name> <param-value>classpath:shiro.ini</param-value> </context-param> <!-- 配置shiro 过滤器 --> <filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> </filter> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
二.三 后端开发
目录结构:
基本与前面的 Servlet 内容一致。
只简单复制几个比较重要的类。
二.三.一 权限查询实现 PrivilegeServiceImpl
有一个方法, getPrivilegeByUId 用于查询权限。
public class PrivilegeServiceImpl implements PrivilegeService { private PrivilegeDao privilegeDao=new PrivilegeDaoImpl(); @Override public List<Privilege> getPrivilegeByUId(Integer uId,Integer type) { //如果类型为空,就查询全部类型的权限 if(type==null){ String sql="select * from privilege a where a.id in ( select rp.pid from user_role ur " + " left join role_privilege rp " +"on ur.rid=rp.rid where ur.uid=? )"; return privilegeDao.findInfosBySql(sql,uId); }else{ //查询指定类型的权限 String sql="select * from privilege a where a.id in ( select rp.pid from user_role ur " + " left join role_privilege rp " +"on ur.rid=rp.rid where ur.uid=? ) and a.type=?"; return privilegeDao.findInfosBySql(sql,uId,type); } } }
二.三.二 根据用户编号查询权限数据 PrivilegeListServlet
package com.yjl.servlet; import java.io.IOException; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.yjl.pojo.Privilege; import com.yjl.service.PrivilegeService; import com.yjl.service.impl.PrivilegeServiceImpl; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import net.sf.json.JsonConfig; @WebServlet("/Privilege/getPrivilegeByUId") public class PrivilegeListServlet extends HttpServlet{ private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //接收用户的编号 PrivilegeService privilegeService=new PrivilegeServiceImpl(); Integer uId=Integer.parseInt(req.getParameter("userId")); privilegeService=new PrivilegeServiceImpl(); //查询全部的菜单 List<Privilege> privilegeList=privilegeService.getPrivilegeByUId(uId,1); java2Json(resp, privilegeList, new String[]{}); } /** * 将指定Java对象转为json,并响应到客户端页面 * @param o * @param exclueds */ public void java2Json(HttpServletResponse resp,@SuppressWarnings("rawtypes") List o ,String[] exclueds){ JsonConfig jsonConfig = new JsonConfig(); //指定哪些属性不需要转json jsonConfig.setExcludes(exclueds); JSONArray objData=JSONArray.fromObject(o,jsonConfig); JSONObject objMap=new JSONObject(); objMap.put("data",objData); objMap.put("status",true); resp.setContentType("text/json;charset=utf-8"); try { resp.getWriter().print(objMap.toString()); } catch (IOException e) { e.printStackTrace(); } } }
二.三.四 登录 UserLoginServlet
package com.yjl.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; 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.session.Session; import org.apache.shiro.subject.Subject; import com.yjl.pojo.User; import net.sf.json.JSONObject; @WebServlet("/User/login") public class UserLoginServlet extends HttpServlet{ private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //找到相应的Subject Subject subject=SecurityUtils.getSubject(); UsernamePasswordToken token=new UsernamePasswordToken(req.getParameter("code"), req.getParameter("password")); try{ subject.login(token); boolean2Json(resp, true); Session session=subject.getSession(); User user=(User)subject.getPrincipal(); session.setAttribute("loginUser", user); }catch(Exception e){ //代码为001,表示用户名或者密码错误 map2Json(resp,"001"); } } /** * 将状态返回到前台,通常是添加,删除,更新的操作,如果错误,则传入错误代码。 * @param o * @param exclueds */ public void map2Json(HttpServletResponse resp,String ... code){ //指定哪些属性不需要转json JSONObject objMap=new JSONObject(); if(code==null||code.length<1){ objMap.put("status",true); }else{ objMap.put("status",false); objMap.put("error_code",code[0]); } resp.setContentType("text/json;charset=utf-8"); try { resp.getWriter().print(objMap.toString()); } catch (IOException e) { e.printStackTrace(); } } /** * 传入是否成功,只返回状态 * @param o * @param exclueds */ public void boolean2Json(HttpServletResponse resp,boolean flag){ //指定哪些属性不需要转json JSONObject objMap=new JSONObject(); objMap.put("status",true); objMap.put("flag",flag); resp.setContentType("text/json;charset=utf-8"); try { resp.getWriter().print(objMap.toString()); } catch (IOException e) { e.printStackTrace(); } } }
二.三.五 退出登录 UserLoginOutServlet
package com.yjl.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; @WebServlet("/User/logout") public class UserLoginOutServlet extends HttpServlet{ private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Subject subject=SecurityUtils.getSubject(); //退出登录 subject.logout(); req.getRequestDispatcher("/WEB-INF/pages/login.jsp").forward(req, resp); } }