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

posted @ 2020-10-28 21:46  C3Stones  阅读(983)  评论(3编辑  收藏  举报