[TOC]

集成Spring Security进行权限控制

1:掌握Spring Security实现认证的过程
2:掌握Spring Security实现授权的过程

第一章. 在项目中使用Spring Security

前面我们已经学习了Spring Security框架的使用方法,本章节我们就需要将Spring Security框架应用到后台系统中进行权限控制,其本质就是认证和授权。
要进行认证和授权需要前面课程中提到的权限模型涉及的7张表支撑,因为用户信息、权限信息、菜单信息、角色信息、关联信息等都保存在这7张表中,也就是这些表中的数据是我们进行认证和授权的依据。所以在真正进行认证和授权之前需要对这些数据进行管理,即我们需要开发如下一些功能:
1、用户数据管理(增删改查、用户关联角色)
2、角色数据管理(增删改查、角色关联权限、角色关联菜单)
3、权限数据管理(增删改查)
4、菜单数据管理(增删改查)
鉴于时间关系,我们不再实现这些数据管理的代码开发。我们可以直接将数据导入到数据库中即可。
导入用户、角色、权限、菜单 的初始数据
— ——————————————
— Table structure for t_user
— ——————————————
DROP TABLE IF EXISTS t_user;
CREATE TABLE t_user (
id int(11) NOT NULL AUTO_INCREMENT,
birthday date DEFAULT NULL,
gender varchar(1) DEFAULT NULL,
username varchar(32) DEFAULT NULL,
password varchar(256) DEFAULT NULL,
remark varchar(32) DEFAULT NULL,
station varchar(1) DEFAULT NULL,
telephone varchar(11) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

— ——————————————
— Records of t_user
— ——————————————
INSERT INTO t_user VALUES (‘1’, null, null, ‘admin’, ‘$2a$10$u/BcsUUqZNWUxdmDhbnoeeobJy6IBsL1Gn/S0dMxI2RbSgnMKJ.4a’, null, null, null);
INSERT INTO t_user VALUES (‘2’, null, null, ‘xiaoming’, ‘$2a$10$3xW2nBjwBM3rx1LoYprVsemNri5bvxeOd/QfmO7UDFQhW2HRHLi.C’, null, null, null);
INSERT INTO t_user VALUES (‘3’, null, null, ‘test’, ‘$2a$10$zYJRscVUgHX1wqwu90WereuTmIg6h/JGirGG4SWBsZ60wVPCgtF8W’, null, null, null);

— ——————————————
— Table structure for t_role
— ——————————————
DROP TABLE IF EXISTS t_role;
CREATE TABLE t_role (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(32) DEFAULT NULL,
keyword varchar(64) DEFAULT NULL,
description varchar(128) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

— ——————————————
— Records of t_role
— ——————————————
INSERT INTO t_role VALUES (‘1’, ‘系统管理员’, ‘ROLE_ADMIN’, null);
INSERT INTO t_role VALUES (‘2’, ‘导游’, ‘ROLE_HEALTH_MANAGER’, null);

— ——————————————
— Table structure for t_user_role
— ——————————————
DROP TABLE IF EXISTS t_user_role;
CREATE TABLE t_user_role (
user_id int(11) NOT NULL,
role_id int(11) NOT NULL,
PRIMARY KEY (user_id,role_id),
KEY FK_Reference_8 (role_id),
CONSTRAINT FK_Reference_7 FOREIGN KEY (user_id) REFERENCES t_user (id),
CONSTRAINT FK_Reference_8 FOREIGN KEY (role_id) REFERENCES t_role (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

— ——————————————
— Records of t_user_role
— ——————————————
INSERT INTO t_user_role VALUES (‘1’, ‘1’);
INSERT INTO t_user_role VALUES (‘2’, ‘2’);

— ——————————————
— Table structure for t_permission
— ——————————————
DROP TABLE IF EXISTS t_permission;
CREATE TABLE t_permission (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(32) DEFAULT NULL,
keyword varchar(64) DEFAULT NULL,
description varchar(128) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;

— ——————————————
— Records of t_permission
— ——————————————
INSERT INTO t_permission VALUES (‘1’, ‘新增自由行’, ‘TRAVELITEM_ADD’, null);
INSERT INTO t_permission VALUES (‘2’, ‘删除自由行’, ‘TRAVELITEM_DELETE’, null);
INSERT INTO t_permission VALUES (‘3’, ‘编辑自由行’, ‘TRAVELITEM_EDIT’, null);
INSERT INTO t_permission VALUES (‘4’, ‘查询自由行’, ‘TRAVELITEM_QUERY’, null);
INSERT INTO t_permission VALUES (‘5’, ‘新增跟团游’, ‘TRAVELGROUP_ADD’, null);
INSERT INTO t_permission VALUES (‘6’, ‘删除跟团游’, ‘TRAVELGROUP_DELETE’, null);
INSERT INTO t_permission VALUES (‘7’, ‘编辑跟团游’, ‘TRAVELGROUP_EDIT’, null);
INSERT INTO t_permission VALUES (‘8’, ‘查询跟团游’, ‘TRAVELGROUP_QUERY’, null);
INSERT INTO t_permission VALUES (‘9’, ‘新增套餐’, ‘SETMEAL_ADD’, null);
INSERT INTO t_permission VALUES (‘10’, ‘删除套餐’, ‘SETMEAL_DELETE’, null);
INSERT INTO t_permission VALUES (‘11’, ‘编辑套餐’, ‘SETMEAL_EDIT’, null);
INSERT INTO t_permission VALUES (‘12’, ‘查询套餐’, ‘SETMEAL_QUERY’, null);
INSERT INTO t_permission VALUES (‘13’, ‘预约设置’, ‘ORDERSETTING’, null);
INSERT INTO t_permission VALUES (‘14’, ‘查看统计报表’, ‘REPORT_VIEW’, null);
INSERT INTO t_permission VALUES (‘15’, ‘新增菜单’, ‘MENU_ADD’, null);
INSERT INTO t_permission VALUES (‘16’, ‘删除菜单’, ‘MENU_DELETE’, null);
INSERT INTO t_permission VALUES (‘17’, ‘编辑菜单’, ‘MENU_EDIT’, null);
INSERT INTO t_permission VALUES (‘18’, ‘查询菜单’, ‘MENU_QUERY’, null);
INSERT INTO t_permission VALUES (‘19’, ‘新增角色’, ‘ROLE_ADD’, null);
INSERT INTO t_permission VALUES (‘20’, ‘删除角色’, ‘ROLE_DELETE’, null);
INSERT INTO t_permission VALUES (‘21’, ‘编辑角色’, ‘ROLE_EDIT’, null);
INSERT INTO t_permission VALUES (‘22’, ‘查询角色’, ‘ROLE_QUERY’, null);
INSERT INTO t_permission VALUES (‘23’, ‘新增用户’, ‘USER_ADD’, null);
INSERT INTO t_permission VALUES (‘24’, ‘删除用户’, ‘USER_DELETE’, null);
INSERT INTO t_permission VALUES (‘25’, ‘编辑用户’, ‘USER_EDIT’, null);
INSERT INTO t_permission VALUES (‘26’, ‘查询用户’, ‘USER_QUERY’, null);

— ——————————————
— Table structure for t_role_permission
— ——————————————
DROP TABLE IF EXISTS t_role_permission;
CREATE TABLE t_role_permission (
role_id int(11) NOT NULL,
permission_id int(11) NOT NULL,
PRIMARY KEY (role_id,permission_id),
KEY FK_Reference_12 (permission_id),
CONSTRAINT FK_Reference_11 FOREIGN KEY (role_id) REFERENCES t_role (id),
CONSTRAINT FK_Reference_12 FOREIGN KEY (permission_id) REFERENCES t_permission (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

— ——————————————
— Records of t_role_permission
— ——————————————
INSERT INTO t_role_permission VALUES (‘1’, ‘1’);
INSERT INTO t_role_permission VALUES (‘2’, ‘1’);
INSERT INTO t_role_permission VALUES (‘1’, ‘2’);
INSERT INTO t_role_permission VALUES (‘2’, ‘2’);
INSERT INTO t_role_permission VALUES (‘1’, ‘3’);
INSERT INTO t_role_permission VALUES (‘2’, ‘3’);
INSERT INTO t_role_permission VALUES (‘1’, ‘4’);
INSERT INTO t_role_permission VALUES (‘2’, ‘4’);
INSERT INTO t_role_permission VALUES (‘1’, ‘5’);
INSERT INTO t_role_permission VALUES (‘2’, ‘5’);
INSERT INTO t_role_permission VALUES (‘1’, ‘6’);
INSERT INTO t_role_permission VALUES (‘2’, ‘6’);
INSERT INTO t_role_permission VALUES (‘1’, ‘7’);
INSERT INTO t_role_permission VALUES (‘2’, ‘7’);
INSERT INTO t_role_permission VALUES (‘1’, ‘8’);
INSERT INTO t_role_permission VALUES (‘2’, ‘8’);
INSERT INTO t_role_permission VALUES (‘1’, ‘9’);
INSERT INTO t_role_permission VALUES (‘2’, ‘9’);
INSERT INTO t_role_permission VALUES (‘1’, ‘10’);
INSERT INTO t_role_permission VALUES (‘2’, ‘10’);
INSERT INTO t_role_permission VALUES (‘1’, ‘11’);
INSERT INTO t_role_permission VALUES (‘2’, ‘11’);
INSERT INTO t_role_permission VALUES (‘1’, ‘12’);
INSERT INTO t_role_permission VALUES (‘2’, ‘12’);
INSERT INTO t_role_permission VALUES (‘1’, ‘13’);
INSERT INTO t_role_permission VALUES (‘2’, ‘13’);
INSERT INTO t_role_permission VALUES (‘1’, ‘14’);
INSERT INTO t_role_permission VALUES (‘2’, ‘14’);
INSERT INTO t_role_permission VALUES (‘1’, ‘15’);
INSERT INTO t_role_permission VALUES (‘1’, ‘16’);
INSERT INTO t_role_permission VALUES (‘1’, ‘17’);
INSERT INTO t_role_permission VALUES (‘1’, ‘18’);
INSERT INTO t_role_permission VALUES (‘1’, ‘19’);
INSERT INTO t_role_permission VALUES (‘1’, ‘20’);
INSERT INTO t_role_permission VALUES (‘1’, ‘21’);
INSERT INTO t_role_permission VALUES (‘1’, ‘22’);
INSERT INTO t_role_permission VALUES (‘1’, ‘23’);
INSERT INTO t_role_permission VALUES (‘1’, ‘24’);
INSERT INTO t_role_permission VALUES (‘1’, ‘25’);
INSERT INTO t_role_permission VALUES (‘1’, ‘26’);

— ——————————————
— Table structure for t_menu
— ——————————————
DROP TABLE IF EXISTS t_menu;
CREATE TABLE t_menu (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(128) DEFAULT NULL,
linkUrl varchar(128) DEFAULT NULL,
path varchar(128) DEFAULT NULL,
priority int(11) DEFAULT NULL,
icon varchar(64) DEFAULT NULL,
description varchar(128) DEFAULT NULL,
parentMenuId int(11) DEFAULT NULL,
level int(11) DEFAULT NULL,
PRIMARY KEY (id),
KEY FK_Reference_13 (parentMenuId),
CONSTRAINT FK_Reference_13 FOREIGN KEY (parentMenuId) REFERENCES t_menu (id)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;

— ——————————————
— Records of t_menu
— ——————————————
INSERT INTO t_menu VALUES (‘1’, ‘会员管理’, null, ‘2’, ‘1’, ‘fa-user-md’, null, null, ‘1’);
INSERT INTO t_menu VALUES (‘2’, ‘会员档案’, ‘member.html’, ‘/2-1’, ‘1’, null, null, ‘1’, ‘2’);
INSERT INTO t_menu VALUES (‘3’, ‘会员信息上传’, null, ‘/2-2’, ‘2’, null, null, ‘1’, ‘2’);
INSERT INTO t_menu VALUES (‘4’, ‘会员统计’, null, ‘/2-3’, ‘3’, null, null, ‘1’, ‘2’);
INSERT INTO t_menu VALUES (‘5’, ‘预约管理’, null, ‘3’, ‘2’, ‘fa-tty’, null, null, ‘1’);
INSERT INTO t_menu VALUES (‘6’, ‘预约列表’, ‘ordersettinglist.html’, ‘/3-1’, ‘1’, null, null, ‘5’, ‘2’);
INSERT INTO t_menu VALUES (‘7’, ‘预约设置’, ‘ordersetting.html’, ‘/3-2’, ‘2’, null, null, ‘5’, ‘2’);
INSERT INTO t_menu VALUES (‘8’, ‘套餐管理’, ‘setmeal.html’, ‘/3-3’, ‘3’, null, null, ‘5’, ‘2’);
INSERT INTO t_menu VALUES (‘9’, ‘跟团游管理’, ‘checkgroup.html’, ‘/3-4’, ‘4’, null, null, ‘5’, ‘2’);
INSERT INTO t_menu VALUES (‘10’, ‘自由行管理’, ‘checkitem.html’, ‘/3-5’, ‘5’, null, null, ‘5’, ‘2’);
INSERT INTO t_menu VALUES (‘11’, ‘旅游评估’, null, ‘4’, ‘3’, ‘fa-stethoscope’, null, null, ‘1’);
INSERT INTO t_menu VALUES (‘12’, ‘大家一起游’, null, ‘/4-1’, ‘1’, null, null, ‘11’, ‘2’);
INSERT INTO t_menu VALUES (‘13’, ‘统计分析’, null, ‘5’, ‘4’, ‘fa-heartbeat’, null, null, ‘1’);
INSERT INTO t_menu VALUES (‘14’, ‘会员数量’, ‘report_member.html’, ‘/5-1’, ‘1’, null, null, ‘13’, ‘2’);
INSERT INTO t_menu VALUES (‘15’, ‘系统设置’, null, ‘6’, ‘5’, ‘fa-users’, null, null, ‘1’);
INSERT INTO t_menu VALUES (‘16’, ‘菜单管理’, ‘menu.html’, ‘/6-1’, ‘1’, null, null, ‘15’, ‘2’);
INSERT INTO t_menu VALUES (‘17’, ‘权限管理’, ‘permission.html’, ‘/6-2’, ‘2’, null, null, ‘15’, ‘2’);
INSERT INTO t_menu VALUES (‘18’, ‘角色管理’, ‘role.html’, ‘/6-3’, ‘3’, null, null, ‘15’, ‘2’);
INSERT INTO t_menu VALUES (‘19’, ‘用户管理’, ‘user.html’, ‘/6-4’, ‘4’, null, null, ‘15’, ‘2’);
INSERT INTO t_menu VALUES (‘20’, ‘套餐占比’, ‘report_setmeal.html’, ‘/5-2’, ‘2’, null, null, ‘13’, ‘2’);
INSERT INTO t_menu VALUES (‘21’, ‘运营数据’, ‘report_business.html’, ‘/5-3’, ‘3’, null, null, ‘13’, ‘2’);

— ——————————————
— Table structure for t_role_menu
— ——————————————
DROP TABLE IF EXISTS t_role_menu;
CREATE TABLE t_role_menu (
role_id int(11) NOT NULL,
menu_id int(11) NOT NULL,
PRIMARY KEY (role_id,menu_id),
KEY FK_Reference_10 (menu_id),
CONSTRAINT FK_Reference_10 FOREIGN KEY (menu_id) REFERENCES t_menu (id),
CONSTRAINT FK_Reference_9 FOREIGN KEY (role_id) REFERENCES t_role (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

— ——————————————
— Records of t_role_menu
— ——————————————
INSERT INTO t_role_menu VALUES (‘1’, ‘1’);
INSERT INTO t_role_menu VALUES (‘2’, ‘1’);
INSERT INTO t_role_menu VALUES (‘1’, ‘2’);
INSERT INTO t_role_menu VALUES (‘2’, ‘2’);
INSERT INTO t_role_menu VALUES (‘1’, ‘3’);
INSERT INTO t_role_menu VALUES (‘2’, ‘3’);
INSERT INTO t_role_menu VALUES (‘1’, ‘4’);
INSERT INTO t_role_menu VALUES (‘2’, ‘4’);
INSERT INTO t_role_menu VALUES (‘1’, ‘5’);
INSERT INTO t_role_menu VALUES (‘1’, ‘6’);
INSERT INTO t_role_menu VALUES (‘1’, ‘7’);
INSERT INTO t_role_menu VALUES (‘1’, ‘8’);
INSERT INTO t_role_menu VALUES (‘1’, ‘9’);
INSERT INTO t_role_menu VALUES (‘1’, ‘10’);
INSERT INTO t_role_menu VALUES (‘1’, ‘11’);
INSERT INTO t_role_menu VALUES (‘1’, ‘12’);
INSERT INTO t_role_menu VALUES (‘1’, ‘13’);
INSERT INTO t_role_menu VALUES (‘1’, ‘14’);
INSERT INTO t_role_menu VALUES (‘1’, ‘15’);
INSERT INTO t_role_menu VALUES (‘1’, ‘16’);
INSERT INTO t_role_menu VALUES (‘1’, ‘17’);
INSERT INTO t_role_menu VALUES (‘1’, ‘18’);
INSERT INTO t_role_menu VALUES (‘1’, ‘19’);
INSERT INTO t_role_menu VALUES (‘1’, ‘20’);
INSERT INTO t_role_menu VALUES (‘1’, ‘21’);

【目标】

在美年旅游的项目中使用SpringSecurity完成认证和授权

【路径】

1:导入SpringSecurity环境
(1)pom.xml中添加依赖
(2)web.xml添加代理过滤器
2:实现认证和授权
(1)认证:SpringSecurityUserService.java
(2)创建Service类、Dao接口类、Mapper映射文件
(3)springmvc.xml(dubbo注解扫描范围扩大)
(4)spring-security.xml
(5)springmvc.xml(导入spring-security.xml)
(6)TravelItemController类(@PreAuthorize(“hasAuthority(‘CHECKITEM_ADD’)”):完成权限)
(7)travelitem.html(如果没有权限,可以提示错误信息)
(8)导入login.html测试登录
3:显示用户名
4:用户退出

【讲解】

1.1. 导入Spring Security环境

【路径】
1:pom.xml导入坐标
2:web.xml添加代理过滤器

1.1.1. 第一步:pom.xml导入坐标

在meinian_parent父工程的pom.xml中导入Spring Security的maven坐标(已经引入)
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>

1.1.2. 第二步:web.xml添加代理过滤器

在 meinian_web工程的web.xml文件中配置用于整合Spring Security框架的过滤器DelegatingFilterProxy
<filter>

<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/</url-pattern>
</*filter-mapping
>

1.1.3 第三步 :sql语句

1 使用登录名查询用户信息
SELECT FROM t_user WHERE username = ‘admin’
# 2 传递用户id查询角色集合
SELECT r.
FROM t_role r,t_user_role ur WHERE ur.role_id = r.id AND ur.user_id = 1
# 3 传递角色id查询权限集合
SELECT p. FROM t_permission p,t_role_permission rp WHERE p.id = rp.permission_id *AND rp.role_id = 1

1.2. 实现认证和授权

1.2.1. 第一步:SpringSecurityUserService.java

在meinian_web工程中按照Spring Security框架要求提供SpringSecurityUserService,并且实现UserDetailsService接口
package com.atguigu.security;

import com.alibaba.dubbo.config.annotation.Reference;
import com.atguigu.pojo.Permission;
import com.atguigu.pojo.Role;
import com.atguigu.service.UserService;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;

@Component
public class SpringSecurityUserService implements UserDetailsService {

@Reference //注意:此处要通过dubbo远程调用用户服务<br />    **private** UserService userService;

//根据用户名查询用户信息<br />    **public** UserDetails **loadUserByUsername**(String username) **throws** UsernameNotFoundException {<br />        //远程调用用户服务,根据用户名查询用户信息<br />        com.atguigu.pojo.User user = userService.findUserByUsername(username);<br />        **if**(user == **null**){<br />            //用户名不存在,抛出异常UsernameNotFoundException <br />            **return** **null**;<br />        }<br />        List<GrantedAuthority> list = **new** ArrayList<GrantedAuthority>();<br />        Set<Role> roles = user.getRoles();<br />        **for**(Role role : roles){<br />            Set<Permission> permissions = role.getPermissions();<br />            **for**(Permission permission : permissions){<br />                //授权<br />                list.add(**new** SimpleGrantedAuthority(permission.getKeyword()));<br />            }<br />        }<br />        /**<br />         * User()<br />         * 1:指定用户名<br />         * 2:指定密码(SpringSecurity会自动对密码进行校验)<br />         * 3:传递授予的角色和权限<br />         */<br />        UserDetails userDetails = **new** User(username,user.getPassword(),list);<br />        **return** userDetails;<br />    }<br />}<br />使用debug跟踪调试,查看user。<br />![](https://cdn.nlark.com/yuque/0/2021/png/25621085/1639788970533-49b93eb0-a321-421a-8159-c3c2d6b74a77.png#crop=0&crop=0&crop=1&crop=1&id=XULTk&originHeight=619&originWidth=816&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)

1.2.2. 第二步:Service、Dao接口、Mapper映射文件

创建UserService服务接口、服务实现类、Dao接口、Mapper映射文件等
【路径】
1:UserService.java接口
2:UserServiceImpl.java类
3:UserDao.java(使用用户id查询用户)
4:RoleDao.java(使用用户id查询角色集合)
5:PermissionDao.java(使用角色id查询权限集合)
6:UserDao.xml(使用用户id查询用户)
7:RoleDao.xml(使用用户id查询角色集合)
8:PermissionDao.xml(使用角色id查询权限集合)
【讲解】
1:服务接口
package com.atguigu.service;

import com.atguigu.pojo.User;

/
用户服务接口
/
public interface UserService {
User
findUserByUsername(String username);
}
2:服务实现类
package** com.atguigu.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.atguigu.dao.UserDao;
import com.atguigu.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

@Service(interfaceClass = UserService.class)
@Transactional
public class UserServiceImpl implements UserService {

@Autowired<br />    **private** UserDao userDao;

**public** User **findUserByUsername**(String username) {<br />        User user = userDao.findUserByUsername(username);<br />        **return** user;<br />    }<br />}<br />3:Dao接口<br />(1)UserDao<br />**package** com.atguigu.dao;

import com.atguigu.pojo.User;
import org.springframework.stereotype.Repository;

/
持久层Dao接口
/
@Repository
public interface UserDao {
User
findUserByUsername(String username);
}
(2)RoleDao
package** com.atguigu.dao;

import com.atguigu.pojo.Role;
import org.springframework.stereotype.Repository;
import java.util.Set;

/
持久层Dao接口
/
@Repository
public interface RoleDao {
Set
findRolesByUserId(Integer userId);
}
(3)PermissionDao
package** com.atguigu.dao;

import com.atguigu.pojo.Permission;
import org.springframework.stereotype.Repository;
import java.util.Set;

/
持久层Dao接口
/
@Repository
public interface PermissionDao {
Set
findPermissionsByRoleId(Integer roleId);
}
4:Mapper映射文件
(1)UserDao.xml
<?xml version=”1.0” encoding=”UTF-8” ?>
<!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
http://mybatis.org/dtd/mybatis-3-mapper.dtd“ >
<
mapper namespace=”com.atguigu.dao.UserDao”>
<
resultMap id=”userMap” type=”com.atguigu.pojo.User”>
<
id column=”id” property=”id”></id>
<
result column=”birthday” property=”birthday”></result>
<
result column=”gender” property=”gender”></result>
<
result column=”username” property=”username”></result>
<
result column=”password” property=”password”></result>
<
result column=”remark” property=”remark”></result>
<
result column=”station” property=”station”></result>
<
result column=”telephone” property=”telephone”></result>
<
collection property=”roles” column=”id” select=”com.atguigu.dao.RoleDao.findRolesByUserId”></collection>
</
resultMap>
<
select id=”findUserByUsername” parameterType=”string” resultMap=”userMap”>
select u.* from t_user u where username = #{username}
</
select>
</
mapper>
(2)RoleDao.xml
<?xml version=”1.0” encoding=”UTF-8” ?>
<!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
http://mybatis.org/dtd/mybatis-3-mapper.dtd“ >
<
mapper namespace=”com.atguigu.dao.RoleDao”>
<
resultMap id=”roleMap” type=”role”>
<
id column=”id” property=”id”></id>
<
result column=”name” property=”name”></result>
<
result column=”keyword” property=”keyword”></result>
<
result column=”description” property=”description”></result>
<
collection property=”permissions” column=”id” select=”com.atguigu.dao.PermissionDao.findPermissionsByRoleId”></collection>
</
resultMap>
<
select id=”findRolesByUserId” parameterType=”int” resultMap=”roleMap”>
SELECT r.* FROM t_role r,t_user_role ur WHERE r.id = ur.role_id AND ur.user_id = #{userId}
</
select>
</
mapper>
(3)PermissionDao.xml
<?xml version=”1.0” encoding=”UTF-8” ?>
<!DOCTYPE mapper PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
http://mybatis.org/dtd/mybatis-3-mapper.dtd“ >
<
mapper namespace=”com.atguigu.dao.PermissionDao”>
<
select id=”findPermissionsByRoleId” parameterType=”int” resultType=”com.atguigu.pojo.Permission”>
SELECT p.* FROM t_permission p,t_role_permission rp WHERE p.id = rp.permission_id AND rp.role_id = #{roleId}
</
select>
</
mapper**>

1.2.3. 第三步:springmvc.xml

修改meinian_web工程中的springmvc.xml文件,修改dubbo批量扫描的包路径
之前的包扫描

<dubbo:annotation package=”com.atguigu.controller” />
现在的包扫描

<dubbo:annotation package=”com.atguigu” />
注意:此处原来扫描的包为com.atguigu.controller,现在改为com.atguigu包的目的是需要将我们上面定义的SpringSecurityUserService也扫描到,因为在SpringSecurityUserService的loadUserByUsername方法中需要通过dubbo远程调用名称为UserService的服务。

1.2.4. 第四步:spring-security.xml

【路径】
1:定义哪些链接可以放行
2:定义哪些链接不可以放行,即需要有角色、权限才可以放行
3:认证管理,定义登录账号名和密码,并授予访问的角色、权限
4:设置在页面可以通过iframe访问受保护的页面,默认为不允许访问,需要添加security:frame-options policy=“SAMEORIGIN”
【讲解】
在meinian_web工程中提供spring-security.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:security=”http://www.springframework.org/schema/security
xsi:schemaLocation=”http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd”>


<security:http security=”none” pattern=”/js/“ />
<
security:http security=”none” pattern=”/css/“ />
<security:http security=”none” pattern=”/img/“ />
<
security:http security=”none” pattern=”/plugins/“ />
<security:http security=”none” pattern=”/login.html” />

<security:global-method-security pre-post-annotations=”enabled” />

<security:http auto-config=”true” use-expressions=”true”>

    <!--只要认证通过就可以访问--><br />        <!--<br />            intercept-url:定义一个拦截规则<br />            pattern:对哪些url进行权限控制<br />            access:在请求对应的URL时需要什么权限,默认配置时它应该是一个以逗号分隔的角色列表,<br />              请求的用户只需拥有其中的一个角色就能成功访问对应的URL<br />            isAuthenticated():需要经过认证后才能访问(不是匿名用户)<br />        --><br />        <**security:intercept-url** **pattern**="/pages/**"  **access**="isAuthenticated()" />

    <!--<br />          form-login:定义表单登录信息<br />        --><br />        <**security:form-login** **login-page**="/login.html"<br />                             **username-parameter**="username"<br />                             **password-parameter**="password"<br />                             **login-processing-url**="/login.do"<br />                             **default-target-url**="/pages/main.html"<br />                             **authentication-failure-url**="/login.html"<br />                             **always-use-default-target**="true"<br />        />

    <!--<br />          csrf:对应CsrfFilter过滤器<br />          disabled:是否启用CsrfFilter过滤器,如果使用自定义登录页面需要关闭此项,否则登录操作会被禁用(403)<br />        --><br />        <**security:csrf** **disabled**="true"></**security:csrf**>

    <!--<br />          logout:退出登录<br />          logout-url:退出登录操作对应的请求路径<br />          logout-success-url:退出登录后的跳转页面<br />        --><br />        <**security:logout** **logout-url**="/logout.do" **logout-success-url**="/login.html" **invalidate-session**="true"/><br />    </**security:http**>


<!--配置密码加密对象--><br />    <**bean** **id**="passwordEncoder" **class**="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />


<!--<br />        三:认证管理,定义登录账号名和密码,并授予访问的角色、权限<br />        authentication-manager:认证管理器,用于处理认证操作<br />    --><br />    <**security:authentication-manager**><br />        <!--<br />            authentication-provider:认证提供者,执行具体的认证逻辑<br />        --><br />        <**security:authentication-provider** **user-service-ref**="springSecurityUserService"><br />            <!--指定密码加密策略--><br />            <**security:password-encoder** **ref**="passwordEncoder"></**security:password-encoder**><br />        </**security:authentication-provider**><br />    </**security:authentication-manager**>

</beans>
这里注意:如果出现以下问题
11_美年旅游_集成权限框架_V1.0 - 图1
使用下面的配置,在spring-security.xml中添加。
放置到里面
<security:headers>

<security:frame-options policy=”SAMEORIGIN”></security:frame-options>
</security:headers>
是因为我们在main.html中定义:如果不配置springSecurity会认为iframe访问的html页面是受保护的页面,不允许访问。
<el-container>
<iframe name=”right” class=”el-main” src=”travelitem.html” width=”100%” height=”580px” frameborder=”0”></iframe>
</el-container>
备注:
11_美年旅游_集成权限框架_V1.0 - 图2

1.2.5. 第五步:springmvc.xml

在springmvc.xml文件中引入spring-security.xml文件
<import resource=”classpath:spring-security.xml”></import>

1.2.6. 第六步:TravelItemController类

在Controller的方法上加入权限控制注解,此处以 TravelItemController 为例
package com.atguigu.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.atguigu.constant.MessageConstant;
import com.atguigu.entity.PageResult;
import com.atguigu.entity.QueryPageBean;
import com.atguigu.entity.Result;
import com.atguigu.pojo.TravelItem;
import com.atguigu.service.TravelItemService;
import com.github.pagehelper.Page;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController
@RequestMapping(“/travelItem”)
public class TravelItemController {

@Reference<br />    **private** TravelItemService travelItemService;

@RequestMapping("/findAll")<br />    **public** Result **findAll**(){<br />        List<TravelItem> lists =  travelItemService.findAll();<br />        **return** **new** **Result**(**true**,MessageConstant.QUERY_TRAVELITEM_SUCCESS,lists);<br />    }


@RequestMapping("/edit")<br />    @PreAuthorize("hasAuthority('TRAVELITEM_EDIT')")//权限校验<br />    **public** Result **edit**(@RequestBody TravelItem travelItem){<br />        travelItemService.edit(travelItem);<br />        **return** **new** **Result**(**true**,MessageConstant.EDIT_TRAVELITEM_SUCCESS);<br />    }

@RequestMapping("/findById")<br />    **public** Result **findById**(Integer id){<br />        TravelItem travelItem = travelItemService.findById(id);<br />        **return** **new** **Result**(**true**,MessageConstant.QUERY_TRAVELITEM_SUCCESS,travelItem);<br />    }

@RequestMapping("/delete")<br />    @PreAuthorize("hasAuthority('TRAVELITEM_DELETE')")//权限校验,使用TRAVELITEM_DELETE123测试<br />    **public** Result **delete**(Integer id){<br />        **try** {<br />            travelItemService.delete(id);<br />            **return** **new** **Result**(**true**,MessageConstant.DELETE_TRAVELITEM_SUCCESS);<br />        }**catch** (RuntimeException e){<br />            **return** **new** **Result**(**false**,MessageConstant.DELETE_TRAVELITEM_FAIL);<br />        }**catch** (Exception e) {<br />            e.printStackTrace();<br />        }<br />        **return** **new** **Result**(**false**,MessageConstant.DELETE_TRAVELITEM_FAIL);<br />    }

@RequestMapping("/findPage")<br />    @PreAuthorize("hasAuthority('TRAVELITEM_QUERY')")//权限校验<br />    **public** PageResult **findPage**(@RequestBody QueryPageBean queryPageBean){<br />        PageResult pageResult =  travelItemService.findPage(queryPageBean.getCurrentPage(),<br />                queryPageBean.getPageSize(),queryPageBean.getQueryString());<br />        **return** pageResult;<br />    }


//@RequestBody:表示对象和json数据进行互转<br />    @RequestMapping("/add")<br />    @PreAuthorize("hasAuthority('TRAVELITEM_ADD')")//权限校验<br />    **public** Result **add**(@RequestBody TravelItem travelItem){<br />        **try** {<br />            // 增加,更新,删除 ,就不需要往data里面添加数据<br />            // 查询:list 对象<br />            travelItemService.add(travelItem);<br />            Result result = **new** Result(**true**, MessageConstant.ADD_TRAVELITEM_SUCCESS);<br />            **return** result;<br />        } **catch** (Exception e) {<br />            e.printStackTrace();<br />        }<br />        **return** **new** **Result**(**false**, MessageConstant.ADD_TRAVELITEM_SUCCESS);<br />    }

}

1.2.7. 第七步:CustomAccessDeniedHandler类

添加页面,没有权限时提示信息设置。

  1. 标签中增加



2.增加自定义处理类
package com.atguigu.security;

import com.alibaba.fastjson.JSON;
import com.atguigu.entity.Result;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/
无权访问处理类
/
@Component
public class
CustomAccessDeniedHandler implements AccessDeniedHandler** {

@Override<br />    public void **handle**(HttpServletRequest request,HttpServletResponse response,<br />                       AccessDeniedException accessDeniedException) throws IOException,ServletException {<br />        if (isAjaxRequest(request)) {// AJAX请求,使用response发送403<br />            Result result = new Result(false, "无权访问","403");<br />            String json = JSON.toJSONString(result);<br />            response.getWriter().print(json);<br />        } else{// 同步请求处理<br />            request.getRequestDispatcher("/pages/error/403.html").forward(request,response);<br />        }<br />    }

/**<br />     * 判断是否为ajax请求<br />     */<br />    public static boolean **isAjaxRequest**(HttpServletRequest request) {<br />        if (request.getHeader("accept").indexOf("application/json") > -1<br />                || (request.getHeader("X-Requested-With") != null && request.getHeader("X-Requested-With").equalsIgnoreCase("XMLHttpRequest"))) {<br />            return true;<br />        }<br />        return false;<br />    }<br />}<br />3.增加/pages/error/403.html页面

1.2.8. 第八步:导入login.html页面

11_美年旅游_集成权限框架_V1.0 - 图3
11_美年旅游_集成权限框架_V1.0 - 图4
此时login.html是可放行的页面,而pages下的页面必须认证之后才能访问的页面

1.3. 显示用户名

【路径】
1:引入js
2:定义username属性
3:使用钩子函数,调用ajax,查询登录用户(从SpringSecurity中获取),赋值username属性
4:修改页面,使用{{username}}显示用户信息
【讲解】
前面我们已经完成了认证和授权操作,如果用户认证成功后需要在页面展示当前用户的用户名。Spring Security在认证成功后会将用户信息保存到框架提供的上下文对象中,所以此处我们就可以调用Spring Security框架提供的API获取当前用户的username并展示到页面上。
实现步骤:
第一步:在main.html页面中修改,定义username模型数据基于VUE的数据绑定展示用户名,发送ajax请求获取username
(1):引入js
<script src=”../js/axios-0.18.0.js”></script>
(2):定义username属性
(3):使用钩子函数,调用ajax