基于Shiro 拦截URL,实现权限控制
CREATE TABLE `t_privilege` ( `id` int(11) NOT NULL auto_increment, `perms` varchar(255) default NULL, `url` varchar(255) default NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;CREATE TABLE `t_user` ( `id` int(11) NOT NULL auto_increment, `password` varchar(255) default NULL, `username` varchar(255) default NULL, `role_id` int(11) default NULL, PRIMARY KEY (`id`), KEY `FKCB63CCB613F1722F` (`role_id`), CONSTRAINT `FKCB63CCB613F1722F` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;CREATE TABLE `t_role` ( `id` int(11) NOT NULL, `name` varchar(255) default NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `t_role_t_privilege` ( `t_role_id` int(11) NOT NULL, `privileges_id` int(11) NOT NULL, PRIMARY KEY (`t_role_id`,`privileges_id`), KEY `FK6947A6C85C5EE234` (`privileges_id`), KEY `FK6947A6C8CF836564` (`t_role_id`), CONSTRAINT `FK6947A6C8CF836564` FOREIGN KEY (`t_role_id`) REFERENCES `t_role` (`id`), CONSTRAINT `FK6947A6C85C5EE234` FOREIGN KEY (`privileges_id`) REFERENCES `t_privilege` (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
?这里设计的就是一个User,一个Role。但是Role有很多的URL。
?
DAO,Service 就不给了。
?
action:
?
?
package com.vti.action;import javax.annotation.Resource;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;import org.springframework.stereotype.Controller;import org.springframework.ui.ModelMap;import org.springframework.web.bind.annotation.RequestMapping;import com.vti.model.User;import com.vti.service.UserService;@Controller@RequestMapping(value="/")public class LoginController {private UserService userService;public UserService getUserService() {return userService;}@Resourcepublic void setUserService(UserService userService) {this.userService = userService;}@RequestMapping(value = "/login")public String login(String username, String password, ModelMap map){if(this.userService.checkUser(username, password)){setLogin(username, password);return "index.do";}else{map.addAttribute("msg", "username or password error !");return "login.jsp";}}@RequestMapping(value = "/index")public String index(HttpServletRequest request, HttpServletResponse response,ModelMap map){Subject currentUser = SecurityUtils.getSubject();User user=userService.getByUserLoginId(currentUser.getPrincipal().toString());map.addAttribute("LoginUser",user);return "index.jsp";}@RequestMapping(value = "/logout")public String logout(HttpServletRequest request, HttpServletResponse response,ModelMap map){Subject currentUser = SecurityUtils.getSubject();currentUser.logout();return "login.jsp";}private void setLogin(String userName, String password) {Subject currentUser = SecurityUtils.getSubject();if (!currentUser.isAuthenticated()) {UsernamePasswordToken token = new UsernamePasswordToken(userName, password);token.setRememberMe(false);currentUser.login(token);}}}
?
?
?
web.xml
?
?
<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><welcome-file-list><welcome-file>login.jsp</welcome-file></welcome-file-list><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:beans.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><filter><filter-name>shiroFilter</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><init-param><param-name>targetFilterLifecycle</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/*</url-pattern><dispatcher>REQUEST</dispatcher><dispatcher>FORWARD</dispatcher><dispatcher>INCLUDE</dispatcher><dispatcher>ERROR</dispatcher></filter-mapping><servlet><servlet-name>springMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:SpringMVC.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>springMVC</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping></web-app>
?
?
?
beans.xml
?
?
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"><context:annotation-config /><context:component-scan base-package="com.vti"></context:component-scan><bean id="dataSource" destroy-method="close" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://localhost:3306/test" /><property name="username" value="root" /><property name="password" value="admin" /><property name="initialSize" value="5" /><property name="maxActive" value="500" /><property name="maxIdle" value="50" /><property name="minIdle" value="10" /><property name="timeBetweenEvictionRunsMillis" value="3600000" /><property name="minEvictableIdleTimeMillis" value="3600000" /></bean><bean id="sessionFactory" ref="dataSource" /><property name="packagesToScan"><list><value>com.vti.model</value></list></property><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key="hibernate.show_sql">true</prop><prop key="hibernate.hbm2ddl.auto">update</prop></props></property></bean><bean id="hibernateTemplate" ref="sessionFactory"></property></bean><bean id="txManager"ref="sessionFactory" /></bean><aop:config><aop:pointcut id="bussinessService" expression="execution(public * com.vti.service.*.*(..))" /><aop:advisor pointcut-ref="bussinessService" advice-ref="txAdvice" /></aop:config><tx:advice id="txAdvice" transaction-manager="txManager"><tx:attributes><tx:method name="save*" propagation="REQUIRED"/><tx:method name="find*" read-only="true"/><tx:method name="get*" read-only="true"/></tx:attributes></tx:advice><bean id="securityManager" ref="shiroDbRealm" /></bean><bean id="shiroDbRealm" /><bean id="chainDefinitionSectionMetaSource" ref="securityManager" /><property name="loginUrl" value="/login.jsp" /><property name="successUrl" value="/index.do" /><property name="unauthorizedUrl" value="/403.htm" /><property name="filterChainDefinitionMap" ref="chainDefinitionSectionMetaSource" /></bean><bean id="lifecycleBeanPostProcessor" depends-on="lifecycleBeanPostProcessor" ></bean><bean ref="securityManager"/></bean></beans>
?
?
?
?
?
ChainDefinitionSectionMetaSource
?
?
package com.vti.shiro;import java.text.MessageFormat;import java.util.Iterator;import java.util.List;import javax.annotation.Resource;import org.apache.shiro.config.Ini;import org.apache.shiro.config.Ini.Section;import org.springframework.beans.factory.FactoryBean;import org.springframework.util.StringUtils;import com.vti.dao.PrivilegeDao;import com.vti.model.Privilege;public class ChainDefinitionSectionMetaSource implements FactoryBean<Ini.Section>{public static final String PREMISSION_STRING="perms["{0}"]";private String filterChainDefinitions;private PrivilegeDao privilegeDao; public PrivilegeDao getPrivilegeDao() {return privilegeDao;} public String getFilterChainDefinitions() {return filterChainDefinitions;} @Resourcepublic void setFilterChainDefinitions(String filterChainDefinitions) { String fiter="";//改正后的url配置 List<Privilege> list = privilegeDao.getAll(); for (Iterator<Privilege> it = list.iterator(); it.hasNext();) { Privilege privilege = it.next(); if(!StringUtils.isEmpty(privilege.getUrl())) { fiter+="/"+privilege.getUrl()+" = authc," +MessageFormat.format(PREMISSION_STRING,privilege.getPerms()) +"\n"; }//追加beans.xml中已经有的过滤 } System.out.println(filterChainDefinitions+fiter);this.filterChainDefinitions = filterChainDefinitions+fiter;}@Resourcepublic void setPrivilegeDao(PrivilegeDao privilegeDao) {this.privilegeDao = privilegeDao;} public Section getObject(){ Ini ini = new Ini();//网上好多都是在这里配置URL的。但是发现是错误的。 ini.load(filterChainDefinitions); Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME); return section; } public Class<?> getObjectType() { return this.getClass(); } public boolean isSingleton() { return false; }}
?
?
?
?
MyShiroRealm
?
?
package com.vti.shiro;import java.util.List;import javax.annotation.Resource;import org.apache.shiro.authc.AccountException;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.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.authz.AuthorizationException;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 org.springframework.util.StringUtils;import com.vti.model.Privilege;import com.vti.model.User;import com.vti.service.UserService;public class MyShiroRealm extends AuthorizingRealm{private UserService userService;public UserService getUserService() {return userService;}@Resourcepublic void setUserService(UserService userService) {this.userService = userService;}@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {if(principals == null){throw new AuthorizationException("principals should not be null");}SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();String username =(String) principals.fromRealm(this.getName()).iterator().next();List<Privilege> privileges = userService.getAllPrivilegeByUserId(username);for(Privilege p : privileges){info.addStringPermission(p.getPerms());}return info;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authecToken){UsernamePasswordToken token = (UsernamePasswordToken)authecToken;if(StringUtils.isEmpty(token.getUsername())){throw new AccountException("用户名不能为空");} User user = userService.getByUserLoginId(token.getUsername());if(user == null){throw new UnknownAccountException("用户名没找到");} else if(user.getPassword().equals(new String(token.getPassword()))){return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), this.getName());} else {throw new AuthenticationException("授权失败");}}}
?
?
?
给出index,jsp
有shiro的标签使用
<%@ page language="java" contentType="text/html; utf-8" 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; utf-8"><title>Insert title here</title></head><body><shiro:authenticated><h3>Login User Can see it</h3><h4>You are ${LoginUser.role.name}, Your name is ${LoginUser.username}</h4></shiro:authenticated><shiro:hasPermission name="set"><a href="3.jsp">系统设置</a><br></shiro:hasPermission><shiro:hasPermission name="view"><a href="2.jsp">总账查看</a><br></shiro:hasPermission><shiro:hasPermission name="sale"><a href="1.jsp">卖货</a><br><br></shiro:hasPermission><shiro:notAuthenticated>Please <a href="login.jsp">login</a> in order to update your credit card information.</shiro:notAuthenticated><shiro:authenticated><a href="logout.do">注销</a></shiro:authenticated></body></html>
?
?
最后讲下逻辑思路:
?
?系统分为三个等级。?分别是:售货员,经理,管理员
?售货员:登录,卖货,注销
经理:查账,登录,卖货,注销
管理员:系统设置,查账,登录,卖货,注销。
?
主要是围绕这样的功能去分配url的。
?
数据库在附件中给出。
?