一、在自定义的realm中进行授权
1、在spring配置文件中,加上访问动作类方法需要的权限
2、在realm中给用户进行授权
/**
* 授权的方法
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection paramPrincipalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//为当前用户授权,只需要将用户的权限添加到info对象中就可以了
/*
* 为当前用户授予area的权限,area对应的是spring配置文件中,指定的访问的动作需要的权限字符串,
* 即: /aeraAction_pageQuery.action = perms["area"]
*/
info.addStringPermission("area");
//TODO 后期授权的时候需要根据登录的用户,从数据库中获取当前用户的权限
return info;
}
二、使用shiro的方法注解方式进行权限控制
1、在spring文件中配置开启shiro的注解支持
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:soap="http://cxf.apache.org/bindings/soap"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://cxf.apache.org/bindings/soap
http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
">
<!-- 连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
<property name="jdbcUrl" value="jdbc:oracle:thin:@192.168.37.128:1521:ORCL" />
<property name="user" value="heima_64" />
<property name="password" value="heima_64" />
</bean>
<!-- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl"
value="jdbc:mysql:///test" /> <property name="user" value="root" /> <property
name="password" value="root" /> </bean> -->
<!-- spring整合JPA -->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 指定扫描的包,存放实体类 -->
<property name="packagesToScan" value="com.itheima.bos.domain" />
<!-- 指定持久层提供者为Hibernate -->
<property name="persistenceProvider">
<bean class="org.hibernate.ejb.HibernatePersistence" />
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!-- 自动建表 -->
<property name="generateDdl" value="true" />
<property name="database" value="ORACLE" />
<property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" />
<property name="showSql" value="true" />
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<!-- 组件扫描 @Server @Controller @Repository -->
<context:component-scan base-package="com.itheima.bos.service,com.itheima.bos.web" />
<!-- 整合 spring data jpa -->
<jpa:repositories base-package="com.itheima.bos.dao" />
<!-- 注册CRM服务的客户端代理对象,用于通过Webservice访问CRM服务 -->
<jaxws:client id="crmClient"
address="http://localhost:8081/crm/webservice/customer" serviceClass="com.itheima.crm.service.CustomerService"></jaxws:client>
<bean id="orderServiceImpl"
class="com.itheima.bos.service.take_delivery.impl.OrderServiceImpl"></bean>
<!-- 注册订单服务 -->
<jaxws:server id="orderService" address="/order">
<jaxws:serviceBean>
<ref bean="orderServiceImpl" />
</jaxws:serviceBean>
</jaxws:server>
<!-- 注册shiro框架的bean(过滤器) ,作用是创建shiro框架相关的一些过滤器,每个过滤器进行不同的权限校验 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 注入shiro框架核心对象,安全管理器 -->
<property name="securityManager" ref="securityManager" />
<!--
private String loginUrl; 登录页面
private String successUrl; 录成功后跳转页面
private String unauthorizedUrl;权限不足时的提示页面 -->
<property name="loginUrl" value="/login.html" />
<property name="successUrl" value="/index.html" />
<property name="unauthorizedUrl" value="/unauthorized.html" />
<!-- 指定URL拦截规则 -->
<property name="filterChainDefinitions">
<!--
authc:代表shiro框架提供的一个过滤器,这个过滤器用于判断当前用户是否已经完成认证,
如果当前用户已经认证,就放行,如果当前用户没有认证,跳转到登录页面
anon:代表shiro框架提供的一个过滤器,允许匿名访问 ,即可以不登录访问
**:代表目录下的所有文件及子目录
-->
<value>
/css/* = anon
/images/* = anon
/js/** = anon
/validatecode.jsp* = anon
/userAction_login.action = anon
/aeraAction_pageQuery.action = perms["area"]
/** = authc
</value>
</property>
</bean>
<bean id="bosRealm" class="com.itheima.bos.shiro.BosRealm" />
<!-- 注册安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="bosRealm" />
</bean>
<!-- 事务注解支持,spring整合shiro时候,需要在事务管理器上加上强制使用代理的配置 -->
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />
<!-- 基于spring自动代理方式为Service类创建代理对象,实现权限控制 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
<!-- 强制使用cglib方式创建代理对象 -->
<property name="proxyTargetClass" value="true"></property>
</bean>
<!-- 切面 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"></property>
</bean>
</beans>
2、在service方法上使用注解
3、要想用户能够进行删除快递员操作,需要进行授权
三、使用shiro的标签进行权限控制
1、在页面引入shiro的标签库
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
2、在realm中给给用户赋予角色
3、在页面中使用标签
四、总结shiro提供的权限控制方式
1、URL过滤器拦截实现权限控制
底层基于shiro框架提供的过滤器,拦截客户端发送的请求,实现权限校验,体现在spring的配置文件中
2、方法注解方式实现权限控制
底层基于cglib代理技术,为Service类创建代理对象,由代理对象实现权限校验,体现在Service类的方法上
3、标签方式实现权限控制
底层基于标签技术,动态展示页面中的元素,体现在jsp页面上
4、编程方式实现权限控制(了解)
框架提供了相应的方法,直接判断当前用户的权限
五、实现用户注销功能
1、改造index.html页面
2、编写UserAction中用户注销的方法
/**
* 用户注销的方法
* @return
*/
@Action(value="", results={
@Result(name="userAction_logout", type="redirect", location="/login.html")
})
public String logout(){
//使用shiro提供的用户退出方法进行退出操作
SecurityUtils.getSubject().logout();
return SUCCESS;
}
六、菜单数据管理
1、导入菜单基础数据
-- ----------------------------
-- Records of T_MENU
-- ----------------------------
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('11', '基础档案', null, '1', null, null);
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('111', '基础档案设置', 'pages/base/archives.html', '1', null, '11');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('112', '收派标准', 'pages/base/standard.html', '2', null, '11');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('113', '班车管理', 'pages/base/vehicle.html', '3', null, '11');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('114', '快递员设置/替班', 'pages/base/courier.html', '4', null, '11');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('115', '区域设置', 'pages/base/area.html', '5', null, '11');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('116', '管理分区', 'pages/base/sub_area.html', '6', null, '11');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('117',
'管理定区/调度排班',
'pages/base/fixed_area.html',
'7',
null,
'11');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('118', '收派时间管理', 'pages/base/take_time.html', '8', null, '11');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('12', '受理', null, '2', null, null);
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('121', '业务受理', 'pages/take_delivery/order.html', '1', null, '12');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('122',
'运单快速录入',
'pages/take_delivery/waybill_quick.html',
'2',
null,
'12');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('123', '运单录入', 'pages/take_delivery/waybill.html', '3', null, '12');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('124',
'运单导入',
'pages/take_delivery/waybill_import.html',
'4',
null,
'12');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('125',
'运单管理',
'pages/take_delivery/waybill_manage.html',
'5',
null,
'12');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('126',
'异调运单',
'pages/take_delivery/different_waybill.html',
'6',
null,
'12');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('127',
'运单打印',
'pages/take_delivery/waybill_print.html',
'7',
null,
'12');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('13', '调度', null, '3', null, null);
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('131',
'查台转单',
'pages/take_delivery/change_work_order.html',
'1',
null,
'13');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('132',
'人工调度',
'pages/take_delivery/dispatcher.html',
'2',
null,
'13');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('133',
'取派调度监控',
'pages/take_delivery/dispatcher_monitor.html',
'3',
null,
'13');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('134',
'签收录入',
'pages/take_delivery/sign_input.html',
'4',
null,
'13');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('135',
'取消签收申请',
'pages/take_delivery/sign_cancel.html',
'5',
null,
'13');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('136',
'宣传任务',
'pages/take_delivery/promotion.html',
'6',
null,
'13');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('14', '分拣管理', null, '4', null, null);
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('141', '入库', 'pages/transit/in_storage.html', '1', null, '14');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('142', '出库', 'pages/transit/out_storage.html', '2', null, '14');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('143', '盘库', 'pages/transit/make_storage.html', '3', null, '14');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('144', '合包', 'pages/transit/compose_package.html', '4', null, '14');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('145',
'到达时间录入',
'pages/transit/arrive_time.html',
'5',
null,
'14');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('146',
'出入库查询',
'pages/transit/in_out_search.html',
'6',
null,
'14');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('147', '库存查询', 'pages/transit/remain_search.html', '7', null, '14');
INSERT INTO T_MENU
(C_ID, C_NAME, C_PAGE, C_PRIORITY, C_DESCRIPTION, C_PID)
VALUES
('148', '合包查询', 'pages/transit/package_search.html', '8', null, '14');
2、使用combotree展示菜单数据
(1)、改造父菜单展示代码
<td>父菜单项</td>
<td>
<input name="parentMenu.id" class="easyui-combotree"
data-options="url:'../../menuAction_listajax.action',required:true"
sytle="width:200px;" />
</td>
(2)、改造Menu实体类中的方法
@OneToMany(mappedBy = "parentMenu",fetch=FetchType.EAGER)//查询menu时候查询出子菜单集合,立即加载
private Set<Menu> childrenMenus = new HashSet<Menu>();
@ManyToOne
@JoinColumn(name = "C_PID")
private Menu parentMenu;
/**
* 为menu转为json添加getText()和getChildren()方法
*/
public String getText(){
return name;
}
public Set<Menu> getChildren(){
return childrenMenus;
}
(3)、编写MenuAction
package com.itheima.bos.web.action.system;
import java.util.List;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import com.itheima.bos.domain.system.Menu;
import com.itheima.bos.service.system.MenuService;
import com.itheima.bos.web.action.common.CommonAction;
/**
* 菜单管理动作类
* @author Administrator
*
*/
@Controller
@Namespace("/")
@ParentPackage("struts-default")
@Scope("prototype")
public class MenuAction extends CommonAction<Menu> {
@Autowired
private MenuService service;
@Action(value="menuAction_listajax")
public String listajax(){
List<Menu> list = service.findTopMenu();
this.list2Json(list, new String[]{"roles","childrenMenus","parentMenu"});
return NONE;
}
}
(4)、编写MenuService
package com.itheima.bos.service.system.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.itheima.bos.dao.system.MenuDao;
import com.itheima.bos.domain.system.Menu;
import com.itheima.bos.service.system.MenuService;
@Service
@Transactional
public class MenuServiceImpl implements MenuService {
@Autowired
private MenuDao dao;
/**
* 查询顶层菜单
*/
public List<Menu> findTopMenu() {
return dao.findByParentMenuIsNull();
}
}
(5)、编写MenuDao
package com.itheima.bos.dao.system;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.itheima.bos.domain.system.Menu;
public interface MenuDao extends JpaRepository<Menu, Integer> {
public List<Menu> findByParentMenuIsNull();
}
(6)、页面效果展示
3、菜单添加功能实现
(1)、修改menu_add.html页面按钮提交事件
(2)、编写后台action代码
/**
* 菜单添加
*/
@Action(value="menuAction_add", results={
@Result(name="success", type="redirect", location="/pages/system/menu.html")
})
public String add(){
service.saveMenu(this.getModel());
return SUCCESS;
}
(3)、编写service层代码
/**
* 保存菜单
*/
public void saveMenu(Menu model) {
if(model.getParentMenu() == null || model.getParentMenu().getId() == 0 ){
model.setParentMenu(null);
}
dao.save(model);
}
4、菜单的分页查询
(1)、menu.html中分页url
(2)、action中代码
/**
* 菜单分页查询
* @throws Exception
*/
@Action(value="menuAction_pageQuery")
public String pageQuery() throws Exception{
//Menu实体类中有page属性,接收参数的时候,如果分页中的page和实体类中的page重复,默认会把参数封装到实体类中的page中,因此要取出来
page = Integer.valueOf(this.getModel().getPage());
if(page == 0){
page = 1;
}
//创建一个pageable对象,封装分页参数,用于分页查询
Pageable pageable = new PageRequest(page - 1, rows);
Page<Menu> page = service.pageQuery(pageable);
this.page2Json(page, new String[]{"roles","childrenMenus","parentMenu"});
return NONE;
}
(3)、service层代码
/**
* 菜单的分页查询方法
*/
public Page<Menu> pageQuery(Pageable pageable) {
return dao.findAll(pageable);
}
七、权限数据管理
1、权限数据的分页查询
(1)、调整权限展示页面的url
(2)、编写PermissionAciton代码
package com.itheima.bos.web.action.system;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import com.itheima.bos.domain.system.Permission;
import com.itheima.bos.service.system.PermissionService;
import com.itheima.bos.web.action.common.CommonAction;
/**
* 权限管理动作类
* @author Administrator
*
*/
@Controller
@Namespace("/")
@ParentPackage("struts-default")
@Scope("prototype")
public class PermissionAction extends CommonAction<Permission> {
@Autowired
private PermissionService service;
/**
* 权限分页查询
* @return
*/
@Action(value="permissionAction_pageQuery")
public String pageQuery(){
Pageable pageable = new PageRequest(page - 1, rows);
Page<Permission> page = service.findByPage(pageable);
this.page2Json(page, new String[]{"roles"});
return NONE;
}
}
(3)、编写PermissionService代码
package com.itheima.bos.service.system.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.itheima.bos.dao.system.PermissionDao;
import com.itheima.bos.domain.system.Permission;
import com.itheima.bos.service.system.PermissionService;
/**
* 权限管理service层
* @author Administrator
*
*/
@Service
@Transactional
public class PermissionServiceImpl implements PermissionService {
@Autowired
private PermissionDao dao;
/**
* 分页查询方法
*/
public Page<Permission> findByPage(Pageable pageable) {
return dao.findAll(pageable);
}
}
(4)、编写PermissionDao代码
package com.itheima.bos.dao.system;
import org.springframework.data.jpa.repository.JpaRepository;
import com.itheima.bos.domain.system.Permission;
public interface PermissionDao extends JpaRepository<Permission, Integer> {
}
2、权限添加
(1)、修改permission_add.html页面
(2)、编写action代码
/**
* 权限添加
*/
@Action(value="permissionAction_add",results={
@Result(name="success", type="redirect", location="/pages/system/permission.html")
})
public String add(){
service.save(this.getModel());
return SUCCESS;
}
(3)、编写Service代码
/**
* 权限添加
*/
public void save(Permission model) {
dao.save(model);
}