SpringBoot + SpringSecurity + Quartz + Layui實現系統權限控制和定時任務


1. 簡介

  Spring Security是一個功能強大且易於擴展的安全框架,主要用於為Java程序提供用戶認證(Authentication)和用戶授權(Authorization)功能。
  本文將之前博客 SpringBoot2.x集成Quartz實現定時任務管理(持久化到數據庫) 改為使用Spring Security進行統一的認證和授權。除了將登錄使用Spring Security管理之外,還增加了角色管理、權限管理等菜單,並對系統的權限進行更加細顆粒度的管理和鑒權,使得系統更加安全,便於和其他系統單點集成。

2. Spring Security相關博客(推薦)

  SpringBoot + SpringSecurity + Mybatis-Plus + JWT實現分布式系統認證和授權
  SpringBoot + SpringSecurity + Mybatis-Plus + JWT + Redis 實現分布式系統認證和授權(刷新Token和Token黑名單)

3. 前期回顧(時間升序)

  SpringBoot + Layui +Mybatis-plus實現簡單后台管理系統(內置安全過濾器)
  SpringBoot基於JustAuth實現第三方授權登錄
  SpringBoot + Layui + JustAuth +Mybatis-plus實現可第三方登錄的簡單后台管理系統
  SpringBoot2.x集成Quartz實現定時任務管理(持久化到數據庫)

4. 初始化數據庫

  在之前數據庫上增加四張表,分別為:

-- ----------------------------
-- Table structure for t_sys_auth
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_auth`;
CREATE TABLE `t_sys_auth`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `auth_name` varchar(50) NOT NULL COMMENT '權限名稱',
  `permission` varchar(200) NULL DEFAULT NULL COMMENT '權限標識',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB COMMENT = '系統權限';

-- ----------------------------
-- Table structure for t_sys_role
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_role`;
CREATE TABLE `t_sys_role`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `role_name` varchar(50) NULL DEFAULT NULL COMMENT '角色名稱',
  `role_code` varchar(50) NOT NULL COMMENT '角色編碼',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB COMMENT = '系統角色';

-- ----------------------------
-- Table structure for t_sys_role_auth
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_role_auth`;
CREATE TABLE `t_sys_role_auth`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `role_id` bigint(20) NULL DEFAULT NULL COMMENT '角色ID',
  `auth_id` bigint(20) NULL DEFAULT NULL COMMENT '權限ID',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB COMMENT = '角色權限關系';

-- ----------------------------
-- Table structure for t_sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_user_role`;
CREATE TABLE `t_sys_user_role`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `user_id` bigint(20) NULL DEFAULT NULL COMMENT '用戶ID',
  `role_id` bigint(20) NULL DEFAULT NULL COMMENT '角色ID',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB COMMENT = '用戶角色關系';

完整的初始化數據庫腳本在項目源碼的db文件夾

5. 代碼迭代

  • 修改pom.xml,增加Spring Security依賴
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.c3stones</groupId>
	<artifactId>spring-security-quartz-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-security-quartz-demo</name>
	<description>Spring Security Quartz Demo</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.8.RELEASE</version>
		<relativePath />
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-quartz</artifactId>
		</dependency>
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.3.1</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>5.4.1</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.jsoup</groupId>
			<artifactId>jsoup</artifactId>
			<version>1.11.3</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
  • 增加剛剛添加的四張表對應的實體、Mapper、Service及Service實現類
      以表t_sys_role為例,增加系統角色實體等類,其他請參考系統角色自行添加。
import java.io.Serializable;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;

import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * 系統角色
 * 
 * @author CL
 *
 */
@Data
@TableName("t_sys_role")
@EqualsAndHashCode(callSuper = false)
public class Role extends Model<Role> implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 角色ID
	 */
	@TableId(type = IdType.AUTO)
	private Integer id;

	/**
	 * 角色名稱
	 */
	private String roleName;

	/**
	 * 角色編碼
	 */
	private String roleCode;

}
import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.c3stones.sys.entity.Role;

/**
 * 系統角色Mapper
 * 
 * @author CL
 *
 */
@Mapper
public interface RoleMapper extends BaseMapper<Role> {

}
import java.util.List;

import javax.validation.constraints.NotNull;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.c3stones.sys.entity.Role;
import com.c3stones.sys.entity.User;
import com.c3stones.sys.entity.UserRole;

/**
 * 系統角色Service
 * 
 * @author CL
 *
 */
public interface RoleService extends IService<Role> {

}
import java.util.List;
import java.util.stream.Collectors;

import javax.validation.constraints.NotNull;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.ListUtils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.c3stones.sys.entity.Role;
import com.c3stones.sys.entity.User;
import com.c3stones.sys.entity.UserRole;
import com.c3stones.sys.mapper.RoleMapper;
import com.c3stones.sys.mapper.UserMapper;
import com.c3stones.sys.mapper.UserRoleMapper;
import com.c3stones.sys.service.RoleService;

import cn.hutool.core.util.StrUtil;

/**
 * 系統角色Service實現
 * 
 * @author CL
 *
 */
@Service
public class RoleSerivceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
}
  • 增加用戶詳情實體,用於系統上下文之間傳遞用戶信息
import java.io.Serializable;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;

import com.c3stones.sys.entity.User;

import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * 系統用戶詳情
 * 
 * @author CL
 *
 */
@Data
@EqualsAndHashCode(callSuper = false)
public class UserDetails extends User
		implements org.springframework.security.core.userdetails.UserDetails, Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 用戶角色
	 */
	private Collection<GrantedAuthority> authorities;

	/**
	 * 賬號是否過期
	 */
	private boolean isAccountNonExpired = false;

	/**
	 * 賬號是否鎖定
	 */
	private boolean isAccountNonLocked = false;

	/**
	 * 證書是否過期
	 */
	private boolean isCredentialsNonExpired = false;

	/**
	 * 賬號是否有效
	 */
	private boolean isEnabled = true;

	/**
	 * 獲得用戶權限
	 */
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return authorities;
	}

	/**
	 * 判斷賬號是否過期
	 */
	@Override
	public boolean isAccountNonExpired() {
		return isAccountNonExpired;
	}

	/**
	 * 判斷賬號是否鎖定
	 */
	@Override
	public boolean isAccountNonLocked() {
		return isAccountNonLocked;
	}

	/**
	 * 判斷證書是否過期
	 */
	@Override
	public boolean isCredentialsNonExpired() {
		return isCredentialsNonExpired;
	}

	/**
	 * 判斷賬號是否有效
	 */
	@Override
	public boolean isEnabled() {
		return isEnabled;
	}

}
  • 增加用戶詳情Service,用於系統登錄認證和獲取用戶角色等信息
      需要添加的基礎的用戶、角色、權限等方法(如查詢用戶角色、角色權限等方法),請下載項目源碼查看。
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.c3stones.security.entity.UserDetails;
import com.c3stones.sys.entity.Role;
import com.c3stones.sys.entity.User;
import com.c3stones.sys.service.RoleService;
import com.c3stones.sys.service.UserService;

/**
 * 用戶登錄Service
 * 
 * @author CL
 *
 */
@Service
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {

	@Autowired
	private UserService userService;

	@Autowired
	private RoleService roleService;

	/**
	 * 根據用戶名查用戶信息
	 * 
	 * @param username 用戶名稱
	 * @return 用戶詳細信息
	 */
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		QueryWrapper<User> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("username", username);
		User user = userService.getOne(queryWrapper);
		if (user != null) {
			UserDetails userDetails = new UserDetails();
			BeanUtils.copyProperties(user, userDetails);

			// 用戶角色
			Set<GrantedAuthority> authorities = new HashSet<>();

			// 查詢用戶角色
			List<Role> roleList = roleService.findByUserId(userDetails.getId());
			roleList.forEach(role -> {
				authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleCode()));
			});

			userDetails.setAuthorities(authorities);

			return userDetails;
		}
		return null;
	}

}
  • 增加用戶登錄驗證處理類
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;

import com.c3stones.security.entity.UserDetails;
import com.c3stones.security.service.UserDetailsService;

import cn.hutool.core.util.StrUtil;

/**
 * 用戶登錄驗證處理類
 * 
 * @author CL
 *
 */
@Component
public class UserAuthenticationProvider implements AuthenticationProvider {

	@Autowired
	private UserDetailsService userDetailsService;

	/**
	 * 身份驗證
	 */
	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		// 獲取用戶名
		String username = (String) authentication.getPrincipal();
		// 獲取密碼
		String password = (String) authentication.getCredentials();

		UserDetails userDetails = (UserDetails) userDetailsService.loadUserByUsername(username);
		if (userDetails == null) {
			throw new UsernameNotFoundException("用戶名不存在");
		}

		if (!StrUtil.equals(username, userDetails.getUsername())
				|| !new BCryptPasswordEncoder().matches(password, userDetails.getPassword())) {
			throw new BadCredentialsException("用戶名或密碼錯誤");
		}

		return new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
	}

	/**
	 * 支持指定的身份驗證
	 */
	@Override
	public boolean supports(Class<?> authentication) {
		return true;
	}

}
  • 增加用戶權限注解處理類
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import com.c3stones.security.entity.UserDetails;
import com.c3stones.sys.entity.Auth;
import com.c3stones.sys.service.AuthService;

/**
 * 用戶權限注解處理類
 * 
 * @author CL
 *
 */
@Component
public class UserPermissionEvaluator implements PermissionEvaluator {

	@Autowired
	private AuthService authService;

	/**
	 * 判斷是否擁有權限
	 * 
	 * @param authentication 用戶身份
	 * @param targetUrl      目標路徑
	 * @param permission     路徑權限
	 * 
	 * @return 是否擁有權限
	 */
	@Override
	public boolean hasPermission(Authentication authentication, Object targetUrl, Object permission) {
		UserDetails userDetails = (UserDetails) authentication.getPrincipal();

		// 用戶權限
		Set<String> permissions = new HashSet<String>();

		// 查詢用戶權限
		List<Auth> authList = authService.findByUserId(userDetails.getId());
		authList.forEach(auth -> {
			permissions.add(auth.getPermission());
		});

		// 判斷是否擁有權限
		if (permissions.stream().filter(p -> (permission.toString().startsWith(p))).count() > 0) {
			return true;
		}
		return false;
	}

	@Override
	public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
			Object permission) {
		return false;
	}

}
  • 增加無權限處理類
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

/**
 * 無權限處理類
 * 
 * @author CL
 *
 */
@Component
public class UserAccessDeniedHandler implements AccessDeniedHandler {

	@Override
	public void handle(HttpServletRequest request, HttpServletResponse response,
			AccessDeniedException accessDeniedException) throws IOException {
		response.sendError(403);
	}

}
  • 增加登錄失敗處理類
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import com.c3stones.common.vo.Response;

/**
 * 登錄失敗處理類
 * 
 * @author CL
 *
 */
@Component
public class UserLoginFailureHandler implements AuthenticationFailureHandler {

	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException {
		Response.responseJson(response, Response.error(500, "登錄失敗", exception.getMessage()));
	}
}
  • 增加登錄成功處理類
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import com.c3stones.common.vo.Response;

/**
 * 登錄成功處理類
 * 
 * @author CL
 *
 */
@Component
public class UserLoginSuccessHandler implements AuthenticationSuccessHandler {

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException {
		Response.responseJson(response, Response.success("登錄成功"));
	}
}
  • 增加登出成功處理類
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

/**
 * 登出成功處理類
 * 
 * @author CL
 *
 */
@Component
public class UserLogoutSuccessHandler implements LogoutSuccessHandler {

	@Override
	public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
			throws IOException {
		SecurityContextHolder.clearContext();
		response.sendRedirect("login");
	}
}
  • 增加未登錄處理類
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

/**
 * 未登錄處理類
 * 
 * @author CL
 *
 */
@Component
public class UserNotLoginHandler implements AuthenticationEntryPoint {

	@Override
	public void commence(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException authException) throws IOException {
		response.sendError(403);
	}
}
  • 增加系統安全核心配置,取代之前的系統配置類、登錄攔截器和登錄相關認證邏輯
      本系統不是前后端分離系統,因此還是通過Session進行管理。
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;

import com.c3stones.security.UserAuthenticationProvider;
import com.c3stones.security.UserPermissionEvaluator;
import com.c3stones.security.handle.UserAccessDeniedHandler;
import com.c3stones.security.handle.UserLoginFailureHandler;
import com.c3stones.security.handle.UserLoginSuccessHandler;
import com.c3stones.security.handle.UserLogoutSuccessHandler;
import com.c3stones.security.handle.UserNotLoginHandler;

import lombok.Setter;

/**
 * 系統安全核心配置
 * 
 * @author CL
 *
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ConfigurationProperties(prefix = "security.web")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	/**
	 * 忽略的URL
	 */
	@Setter
	private List<String> excludes;

	/**
	 * 無權限處理類
	 */
	@Autowired
	private UserAccessDeniedHandler userAccessDeniedHandler;

	/**
	 * 用戶未登錄處理類
	 */
	@Autowired
	private UserNotLoginHandler userNotLoginHandler;

	/**
	 * 用戶登錄成功處理類
	 */
	@Autowired
	private UserLoginSuccessHandler userLoginSuccessHandler;

	/**
	 * 用戶登錄失敗處理類
	 */
	@Autowired
	private UserLoginFailureHandler userLoginFailureHandler;

	/**
	 * 用戶登出成功處理類
	 */
	@Autowired
	private UserLogoutSuccessHandler userLogoutSuccessHandler;

	/**
	 * 用戶登錄驗證
	 */
	@Autowired
	private UserAuthenticationProvider userAuthenticationProvider;

	/**
	 * 用戶權限注解
	 */
	@Autowired
	private UserPermissionEvaluator userPermissionEvaluator;

	/**
	 * 加密方式
	 * 
	 * @return
	 */
	@Bean
	public BCryptPasswordEncoder bCryptPasswordEncoder() {
		return new BCryptPasswordEncoder();
	}

	/**
	 * 注入自定義PermissionEvaluator
	 * 
	 * @return
	 */
	@Bean
	public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler() {
		DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
		handler.setPermissionEvaluator(userPermissionEvaluator);
		return handler;
	}

	/**
	 * 用戶登錄驗證
	 */
	@Override
	protected void configure(AuthenticationManagerBuilder auth) {
		auth.authenticationProvider(userAuthenticationProvider);
	}

	/**
	 * 安全權限配置
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.headers().frameOptions().sameOrigin() // 可以相同域名頁面的frame中展示
				.and().authorizeRequests() // 權限配置
				.antMatchers(excludes.toArray(new String[excludes.size()])).permitAll()// 獲取白名單(不進行權限驗證)
				.anyRequest().authenticated() // 其他的需要登陸后才能訪問
				.and().httpBasic().authenticationEntryPoint(userNotLoginHandler) // 配置未登錄處理類
				.and().formLogin().loginPage("/login").loginProcessingUrl("/login") // 配置登錄URL
				.successHandler(userLoginSuccessHandler) // 配置登錄成功處理類
				.failureHandler(userLoginFailureHandler) // 配置登錄失敗處理類
				.and().logout().logoutUrl("/logout")// 配置登出地址
				.logoutSuccessHandler(userLogoutSuccessHandler) // 配置用戶登出處理類
				.and().exceptionHandling().accessDeniedHandler(userAccessDeniedHandler)// 配置沒有權限處理類
				.and().csrf().disable(); // 禁用跨站請求偽造防護
	}

}
  • 其他角色、權限添加、刪除、綁定等功能,請下載項目源碼,啟動項目查看
  • 給系統Controller添加權限注解(以UserController為例)
import javax.validation.constraints.NotNull;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.c3stones.common.vo.Response;
import com.c3stones.sys.entity.User;
import com.c3stones.sys.service.UserService;

import cn.hutool.crypto.digest.BCrypt;

/**
 * 系統用戶Controller
 * 
 * @author CL
 *
 */
@Controller
@RequestMapping(value = "user")
public class UserController {

	@Autowired
	private UserService userService;

	/**
	 * 查詢列表
	 * 
	 * @return
	 */
	@PreAuthorize(value = "hasPermission('/user/list', 'sys:user:view')")
	@RequestMapping(value = "list")
	public String list() {
		return "pages/sys/userList";
	}

	/**
	 * 查詢列表數據
	 * 
	 * @param user    系統用戶
	 * @param current 當前頁
	 * @param size    每頁顯示條數
	 * @return
	 */
	@PreAuthorize(value = "hasPermission('/user/listData', 'sys:user:view')")
	@RequestMapping(value = "listData")
	@ResponseBody
	public Response<Page<User>> listData(User user, @RequestParam(name = "page") long current,
			@RequestParam(name = "limit") long size) {
		Page<User> page = userService.listData(user, current, size);
		return Response.success(page);
	}

	/**
	 * 新增
	 * 
	 * @return
	 */
	@PreAuthorize(value = "hasPermission('/user/add', 'sys:user:edit')")
	@RequestMapping(value = "add")
	public String add() {
		return "pages/sys/userAdd";
	}

	/**
	 * 檢驗用戶名稱是否唯一
	 * 
	 * @param userName 用戶名稱
	 * @return
	 */
	@PreAuthorize(value = "hasPermission('/user/check', 'sys:user:edit')")
	@RequestMapping(value = "check")
	@ResponseBody
	public Response<Boolean> checkUserName(@NotNull String username) {
		Boolean checkResult = userService.checkUserName(username);
		return Response.success(checkResult);
	}

	/**
	 * 保存
	 * 
	 * @param user 系統用戶
	 * @return
	 */
	@PreAuthorize(value = "hasPermission('/user/save', 'sys:user:edit')")
	@RequestMapping(value = "save")
	@ResponseBody
	public Response<Boolean> save(User user) {
		user.setPassword(BCrypt.hashpw(user.getPassword()));
		boolean result = userService.save(user);
		return Response.success(result);
	}

	/**
	 * 修改
	 * 
	 * @param user  系統用戶
	 * @param model
	 * @return
	 */
	@PreAuthorize(value = "hasPermission('/user/edit', 'sys:user:edit')")
	@RequestMapping(value = "edit")
	public String edit(User user, Model model) {
		Assert.notNull(user.getId(), "ID不能為空");
		model.addAttribute("user", userService.getById(user.getId()));
		return "pages/sys/userEdit";
	}

	/**
	 * 更新
	 * 
	 * @param user 系統用戶
	 * @return
	 */
	@PreAuthorize(value = "hasPermission('/user/update', 'sys:user:edit')")
	@RequestMapping(value = "update")
	@ResponseBody
	public Response<Boolean> update(User user) {
		Assert.notNull(user.getId(), "ID不能為空");
		boolean result = userService.updateById(user);
		return Response.success(result);
	}

	/**
	 * 刪除
	 * 
	 * @param user 系統用戶
	 * @return
	 */
	@PreAuthorize(value = "hasPermission('/user/delete', 'sys:user:edit')")
	@RequestMapping(value = "delete")
	@ResponseBody
	public Response<Boolean> delete(User user) {
		Assert.notNull(user.getId(), "ID不能為空");
		boolean result = userService.removeById(user.getId());
		return Response.success(result);
	}

}

6. 測試

  • 登錄(system/123456或user/123456)
      用戶名或密碼錯誤

      用戶名和密碼正確
  • 系統管理員登錄(system/123456)
  • 用戶管理
  • 用戶角色
  • 角色綁定用戶

  • 角色權限
  • 權限綁定角色

  • 任務調度
  • 普通用戶登錄(user/123456)
  • 刪除用戶

  • 給角色添加用戶
  • 任務調度

7. 項目地址

  spring-security-quartz-demo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM