詳解如何在項目中應用SpringSecurity權限控制
要進行認證和授權需要前面課程中提到的權限模型涉及的7張表支撐,因為用戶信息、權限信息、菜單信息、角色信息、關聯(lián)信息等都保存在這7張表中,也就是這些表中的數(shù)據(jù)是我們進行認證和授權的依據(jù)。所以在真正進行認證和授權之前需要對這些數(shù)據(jù)進行管理,即我們需要開發(fā)如下一些功能:

1、權限數(shù)據(jù)管理(增刪改查)
2、菜單數(shù)據(jù)管理(增刪改查)
3、角色數(shù)據(jù)管理(增刪改查、角色關聯(lián)權限、角色關聯(lián)菜單)
4、用戶數(shù)據(jù)管理(增刪改查、用戶關聯(lián)角色)
數(shù)據(jù)庫數(shù)據(jù)實現(xiàn)導入,簡化上面的4步步驟
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);
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');
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', '新增檢查項', 'CHECKITEM_ADD', null);
INSERT INTO `t_permission` VALUES ('2', '刪除檢查項', 'CHECKITEM_DELETE', null);
INSERT INTO `t_permission` VALUES ('3', '編輯檢查項', 'CHECKITEM_EDIT', null);
INSERT INTO `t_permission` VALUES ('4', '查詢檢查項', 'CHECKITEM_QUERY', null);
INSERT INTO `t_permission` VALUES ('5', '新增檢查組', 'CHECKGROUP_ADD', null);
INSERT INTO `t_permission` VALUES ('6', '刪除檢查組', 'CHECKGROUP_DELETE', null);
INSERT INTO `t_permission` VALUES ('7', '編輯檢查組', 'CHECKGROUP_EDIT', null);
INSERT INTO `t_permission` VALUES ('8', '查詢檢查組', 'CHECKGROUP_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', '查看統(tǒng)計報表', '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`
-- ----------------------------
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', '系統(tǒng)管理員', 'ROLE_ADMIN', null);
INSERT INTO `t_role` VALUES ('2', '健康管理師', 'ROLE_HEALTH_MANAGER', null);
-- ----------------------------
-- 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');
-- ----------------------------
-- 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');
1、Spring Security環(huán)境準備
pom.xml中導入Spring Security的maven坐標,目前版本使用的是
5.0.5.RELEASE,版本如果過高可能就會導致不同的報錯
<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、在health_backend工程的web.xml文件中配置用于整合Spring Security框架的過濾器DelegatingFilterProxy
<!--委派過濾器,用于整合其他框架--> <filter> <!--整合spring security時,此過濾器的名稱固定springSecurityFilterChain--> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <!--注意區(qū)分放置的位置,有嚴格的先后順序--> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2、實現(xiàn)認證和授權
在health_backend工程中按照Spring Security框架要求提供SpringSecurityUserService,并且實現(xiàn)UserDetailsService接口
package com.zcl.security;
import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.pojo.Permission;
import com.itheima.pojo.Role;
import com.itheima.pojo.User;
import com.zcl.service.UserService;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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;
import java.util.Set;
/**
* 項目名稱:health_parent
* 描述:SpringSecurity實現(xiàn)認證和授權
*
* @author zhong
* @date 2022-06-24 12:09
*/
@Component
public class SpringSecurityUserService implements UserDetailsService {
/**
* 使用dubbo網(wǎng)絡遠程調(diào)用服務提供方查詢用戶數(shù)據(jù)
*/
@Reference
private UserService userService;
/**
* 根據(jù)用戶名查詢數(shù)據(jù)庫獲取用戶信息
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.findByUsername(username);
if(user == null) {return null;};
List<GrantedAuthority> list = new ArrayList<>();
// 動態(tài)為當前用戶授權
Set<Role> roles = user.getRoles();
// 遍歷角色集合,為用戶授予角色
for (Role role : roles) {
// 為用戶授予角色
list.add(new SimpleGrantedAuthority(role.getKeyword()));
// 獲取權限
Set<Permission> permissions = role.getPermissions();
// 遍歷權限,為角色授權
for (Permission permission : permissions) {
list.add(new SimpleGrantedAuthority(permission.getKeyword()));
}
}
/*
* 將密碼交由框架比對
* 參數(shù)一:賬號
* 參數(shù)二:查詢數(shù)據(jù)庫的密碼,已加密的
* 參數(shù)三:用戶角色所具有的權限
*/
org.springframework.security.core.userdetails.User UserSecurity = new org.springframework.security.core.userdetails.User(username,user.getPassword(),list);
return UserSecurity;
}
}
創(chuàng)建遠程調(diào)用的UserService接口
public interface UserService {
/**
* 根據(jù)登錄名查詢用戶數(shù)據(jù)
* @param username
* @return
*/
User findByUsername(String username);
}
創(chuàng)建接口實現(xiàn)類
需要注入數(shù)據(jù)訪問層來完成數(shù)據(jù)的查詢,用戶、角色、權限各自創(chuàng)建一個dao和映射文件
package com.zcl.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.pojo.Permission;
import com.itheima.pojo.Role;
import com.itheima.pojo.User;
import com.zcl.dao.PermissionDao;
import com.zcl.dao.RoleDao;
import com.zcl.dao.UserDao;
import com.zcl.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.Set;
/**
* 項目名稱:health_parent
* 描述:用戶服務實現(xiàn)類
*
* @author zhong
* @date 2022-06-24 14:35
*/
@Service(interfaceClass = UserService.class)
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Autowired
private RoleDao roleDao;
@Autowired
private PermissionDao permissionDao;
/**
* 根據(jù)用戶名稱查詢用戶角色信息和關聯(lián)的角色信息,同時需要查詢角色關聯(lián)的權限信息
* @param username
* @return
*/
@Override
public User findByUsername(String username) {
// 1、查詢用戶基本信息,不包含用戶角色信息
User user = userDao.findByUsername(username);
if(user == null){
return null;
}
// 2、根據(jù)用戶查詢的用戶id查詢角色信息
Integer userId = user.getId();
Set<Role> roles = roleDao.findByUserId(userId);
// 3、根據(jù)角色來查詢權限
for (Role role : roles) {
Integer roleId = role.getId();
Set<Permission> permissions = permissionDao.findByRoleId(roleId);
// 讓角色關聯(lián)權限
role.setPermissions(permissions);
}
// 讓用還關聯(lián)角色
user.setRoles(roles);
return user;
}
}
創(chuàng)建【用戶、角色、權限】數(shù)據(jù)訪問層接口
注意:這三個接口都不是在同一個類中的,而是各自獨立的接口類,不要寫在一起
public interface UserDao {
User findByUsername(String username);
}
public interface RoleDao {
Set<Role> findByUserId(Integer userId);
}
public interface PermissionDao {
Set<Permission> findByRoleId(Integer roleId);
}
查詢用戶的Mapper映射文件查詢數(shù)據(jù)
映射文件創(chuàng)建在
resources文件下,注意的是需要與dao接口的包一致
<?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.zcl.dao.UserDao">
<!--根據(jù)用戶名稱查詢用戶信息-->
<select id="findByUsername" parameterType="string" resultType="com.itheima.pojo.User">
select *
from t_user
where username = #{username}
</select>
</mapper>
根據(jù)用戶id查詢角色信息Mapper映射文件查詢
<?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.zcl.dao.RoleDao">
<!--根據(jù)用戶id查詢角色信息-->
<select id="findByUserId" resultType="com.itheima.pojo.Role" parameterType="int">
select r.*
from t_role r,t_user_role ur
where r.id = ur.role_id and ur.user_id = #{user_id}
</select>
</mapper>
根據(jù)角色id查詢角色權限Mapper映射文件
<?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.zcl.dao.PermissionDao">
<!--根據(jù)角色id查詢權限-->
<select id="findByRoleId" resultType="com.itheima.pojo.Permission" parameterType="int">
select p.*
from t_permission p,t_role_permission rp
where p.id = rp.permission_id and rp.role_id = ${role_id}
</select>
</mapper>
修改dubbo的批量掃描
原因:默認配置的dubbo掃描的是Controller包下的,所以我們創(chuàng)建了一個新的包server用于存放權限實現(xiàn)類,而實現(xiàn)類剛好也是使用dubbo來遠程調(diào)用接口查詢數(shù)據(jù)庫的,需要使用到dubbo就需要被掃描到
<!--批量掃描--> <dubbo:annotation package="com.zcl" />
創(chuàng)建springSecurity.xml配置文件
與上一篇的入門案例不同的是,
SpringSecurityUserService認證提供者不需要在配置文件里面創(chuàng)建bean交給spring容器了,因為在類的上面已經(jīng)使用@Component創(chuàng)建,在spring容器中已經(jīng)有了,通過小寫字母即可引用如果引用認證類報紅就不需要管,影響不到程序,只是IDEA的檢測問題
<?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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--配置哪些資源匿名可以訪問的資源(不登錄頁可以訪問)-->
<security:http security="none" pattern="/login.html"></security:http>
<security:http security="none" pattern="/css/**"></security:http>
<security:http security="none" pattern="/js/**"></security:http>
<security:http security="none" pattern="/img/**"></security:http>
<security:http security="none" pattern="/plugins/**"></security:http>
<!--
http:用于定義相關權限控制
auto-config:是否自動配置
設置為true時框架會提供默認的一些配置,例如提供默認的登錄頁面、登出處理等
設置為false時需要顯示提供登錄表單配置,否則會報錯
use-expressions:用于指定intercept-url中的access屬性是否使用表達式
-->
<security:http auto-config="true" use-expressions="true">
<security:headers>
<!--設置在頁面可以通過iframe訪問受保護的頁面,默認為不允許訪問-->
<security:frame-options policy="SAMEORIGIN"></security:frame-options>
</security:headers>
<!--
intercept-url:定義一個攔截規(guī)則
pattern:對哪些url進行權限控制
access:在請求對應的URL時需要什么權限,默認配置時它應該是一個以逗號分隔的角色列表,
請求的用戶只需擁有其中的一個角色就能成功訪問對應的URL
-->
<!--只需要認證通過就可以訪問-->
<security:intercept-url pattern="/pages/**" access="isAuthenticated()"/>
<!--如果我們要使用自己指定的頁面作為登錄頁面,必須配置登錄表單-->
<security:form-login
login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
default-target-url="/pages/main.html"
authentication-failure-url="/login.html"/>
<!--csrf:對應CsrfFilter過濾器
disabled:是否啟用CsrfFilter過濾器,如果使用自定義登錄頁面需要關閉此項,否則登錄操作會被禁用(403) -->
<security:csrf disabled="true"/>
<!--
logout:退出登錄
logout-url:退出登錄操作對應的請求路徑
logout-success-url:退出登錄后的跳轉頁面
-->
<security:logout logout-url="/logout.do" logout-success-url="/login.html" invalidate-session="true"/>
</security:http>
<!--authentication-manager:認證管理器,用于處理認證操作-->
<security:authentication-manager>
<!--authentication-provider:認證提供者,執(zhí)行具體的認證邏輯-->
<security:authentication-provider user-service-ref="springSecurityUserService">
<!--引用密碼加密處理bean-->
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
<!--配置密碼加密對象-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<!--開啟注解方式權限控制-->
<security:global-method-security pre-post-annotations="enabled"/>
</beans>
注意:<security:headers>的配置,如果沒有配置這個對象就會訪問不了嵌套的頁面,哪怕是登錄了也不行
在springmvc.xml配置文件中引入springSecurity.xml配置文件
<import resource="spring-security.xml"/>
測試
賬號為:admin 密碼:admin admin加密后的形式為(存儲到數(shù)據(jù)庫):$2a$10$LPbhiutR34wKvjv3Qb8zBu7piw5hG3.IlQMAI3e/D1Y0DJ/mMSkYa
3、在控制器上實現(xiàn)注解鑒權
注意:是在每一個控制器上面添加不同的權限,設置權限的只不能亂設置需要與數(shù)據(jù)庫進行比對的才可以
// 添加數(shù)據(jù)
@PreAuthorize("hasAuthority('CHECKITEM_ADD')")
// 查詢數(shù)據(jù)
@PreAuthorize("hasAuthority('CHECKITEM_QUERY')")
// 刪除數(shù)據(jù)
@PreAuthorize("hasAuthority('CHECKITEM_DELETE')")
// 修改數(shù)據(jù)
@PreAuthorize("hasAuthority('CHECKITEM_EDIT')")
"hasAuthority('CHECKITEM_ADD')"里面的值需要與數(shù)據(jù)庫的權限值一致

模擬沒有權限刪除數(shù)據(jù):
1、登錄第二個賬戶:xiaoming
2、賬戶中沒有刪除檢查項,所以我們就已刪除來測試
3、點擊刪除的時候前端頁面不會提示,查看后端控制器代碼,發(fā)現(xiàn)被攔截了,如下報錯:
4、切換回有刪除權限的用戶,刪除查看效果
3.1、完善前端頁面訪問權限不足提示
在前端代碼中編寫一個方法被多個請求不成功函數(shù)所調(diào)用
showMessage(r){
if(r == 'Error: Request failed with status code 403'){
//權限不足
this.$message.error('無訪問權限');
return;
}else{
this.$message.error('未知錯誤');
return;
}
}
在所有的請求方法上添加一個catch事件調(diào)用函數(shù)
// 發(fā)送刪除數(shù)據(jù)
axios.get("/checkitem/delete.do?id="+row.id).then((res) => {
// ... 回調(diào)方法
}).catch ((r) => {
this.showMessage(r);
});
當用戶操作時如果沒有權限那么后端控制器就會將請求攔截下來,并在后端控制臺打印攔截提示,同時前端頁面回根據(jù)返回的報錯類型做出無權限的提示信息,從而提高用戶體驗
4、請求獲取當前登錄的用戶名信息
請求控制器獲取用戶名信息返回頁面模型綁定給
username用于展示
// 發(fā)送ajax請求獲取當前登錄的用戶名,展示到頁面中
axios.get("/user/getUsername.do").then((res) => {
if(res.data.flag){
this.username = res.data.data;
}
})
請求后端控制器編寫
@RestController
@RequestMapping("/user")
public class UserController {
@RequestMapping("/getUsername")
public Result getUsername(){
// 當springsecurity完成認證后,會將當前用戶信息保存到框架提供的上下文對象中
User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (user != null) {
System.out.println(user.getUsername());
return new Result(true, MessageConstant.GET_USERNAME_SUCCESS,user.getUsername());
}
return new Result(false, MessageConstant.GET_USERNAME_FAIL);
}
}
5、用戶退出
前端請求
<el-dropdown-item divided> <span style="display:block;"><a href="/logout.do" rel="external nofollow" >退出</a></span> </el-dropdown-item>
后端配置文件中進行退出跳轉設置
<!--
logout:退出登錄
logout-url:退出登錄操作對應的請求路徑
logout-success-url:退出登錄后的跳轉頁面
-->
<security:logout logout-url="/logout.do"
logout-success-url="/login.html" invalidate-session="true"/>
到此這篇關于詳解如何在項目中應用SpringSecurity權限控制的文章就介紹到這了,更多相關SpringSecurity權限控制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
劍指Offer之Java算法習題精講鏈表與字符串及數(shù)組
跟著思路走,之后從簡單題入手,反復去看,做過之后可能會忘記,之后再做一次,記不住就反復做,反復尋求思路和規(guī)律,慢慢積累就會發(fā)現(xiàn)質(zhì)的變化2022-03-03
java Socket無法完全接收返回內(nèi)容的解決方案
這篇文章主要介紹了java Socket無法完全接收返回內(nèi)容的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
ShardingSphere數(shù)據(jù)庫讀寫分離算法及測試示例詳解
這篇文章主要為大家介紹了ShardingSphere數(shù)據(jù)庫讀寫分離算法及測試示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-03-03
SpringMVC數(shù)據(jù)頁響應ModelAndView實現(xiàn)頁面跳轉
本文主要介紹了SpringMVC數(shù)據(jù)頁響應ModelAndView實現(xiàn)頁面跳轉,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07
談談Java中對象,類和this,super,static關鍵字的使用
對象:對象是類的一個實例,有狀態(tài)和行為。類:類是一個模板,它描述一類對象的行為和狀態(tài)。本文就來和大家聊聊Java中對象,類和關鍵字的使用,需要的可以參考一下2022-08-08


