springBoot+springSecurity
本文使用springboot+mybatis+通用mapper+SpringSecurity 实现数据库动态的管理用户、角色、权限管理
1.准备
1:数据库表设计
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `admin`
-- ----------------------------
DROP TABLE IF EXISTS `admin`;
CREATE TABLE `admin` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '密码',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of admin
-- ----------------------------
INSERT INTO `admin` VALUES ('1', 'admin', '$2a$10$7OVUuNSNaG1pz6z1xQ8zt.WrPyzJBJ3PJ7mXfIL7D3hM/hq0kbYUK');
INSERT INTO `admin` VALUES ('2', 'test', '$2a$10$7OVUuNSNaG1pz6z1xQ8zt.WrPyzJBJ3PJ7mXfIL7D3hM/hq0kbYUK');
-- ----------------------------
-- Table structure for `permission`
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL COMMENT '权限名称',
`description` varchar(255) DEFAULT NULL COMMENT '权限描述',
`url` varchar(255) DEFAULT NULL COMMENT 'URL地址',
`pid` int(11) DEFAULT NULL COMMENT '父节点id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of permission
-- ----------------------------
INSERT INTO `permission` VALUES ('1', 'ROLE_HOME', 'home', '/', null);
INSERT INTO `permission` VALUES ('2', 'ROLE_ADMIN', 'test', '/admin', null);
-- ----------------------------
-- Table structure for `permission_role`
-- ----------------------------
DROP TABLE IF EXISTS `permission_role`;
CREATE TABLE `permission_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_id` int(11) NOT NULL COMMENT '角色id',
`permission_id` int(11) NOT NULL COMMENT '权限id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of permission_role
-- ----------------------------
INSERT INTO `permission_role` VALUES ('1', '1', '1');
INSERT INTO `permission_role` VALUES ('2', '1', '2');
INSERT INTO `permission_role` VALUES ('3', '2', '1');
-- ----------------------------
-- Table structure for `role`
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL COMMENT '角色名称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', 'ROLE_ADMIN');
INSERT INTO `role` VALUES ('2', 'ROLE_USER');
-- ----------------------------
-- Table structure for `role_user`
-- ----------------------------
DROP TABLE IF EXISTS `role_user`;
CREATE TABLE `role_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
`role_id` int(11) DEFAULT NULL COMMENT '角色id',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of role_user
-- ----------------------------
INSERT INTO `role_user` VALUES ('1', '1', '1');
INSERT INTO `role_user` VALUES ('2', '2', '2');
2 业务代码
2.1 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.cloudtech</groupId>
<artifactId>demo-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo-2</name>
<description>Demo project for Spring Boot</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- 热部署,不用重启 ,这个在这里不需要 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- mybatis的starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--引入druid数据源 -->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.8</version>
</dependency>
<!--mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--通用Mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.0.3</version>
</dependency>
<!--pageHelper分页 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</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-security</artifactId>
</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>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-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>
2.2 com.cloudtech.auth
2.2.1 CustomUserService.java
package com.cloudtech.auth;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
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.Service;
import com.cloudtech.entity.Admin;
import com.cloudtech.entity.Permission;
import com.cloudtech.service.AdminService;
import com.cloudtech.service.PermissionService;
/**
*
* @ClassName: CustomUserService
* @Description:
* @author wude
* @date 2019年1月11日
*
*/
@Service
public class CustomUserService implements UserDetailsService { //自定义UserDetailsService 接口
@Autowired
private PermissionService permissionService;
@Autowired
private AdminService adminService;
public UserDetails loadUserByUsername(String username) {
Admin admin = adminService.findByUserName(username);
if (admin != null) {
List<Permission> permissions = permissionService.findByAdminUserId(admin.getId());
List<GrantedAuthority> grantedAuthorities = new ArrayList <>();
for (Permission permission : permissions) {
if (permission != null && permission.getName()!=null) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName());
//1:此处将权限信息添加到 GrantedAuthority 对象中,在后面进行全权限验证时会使用GrantedAuthority 对象。
grantedAuthorities.add(grantedAuthority);
}
}
return new User(admin.getUsername(), admin.getPassword(), grantedAuthorities);
} else {
throw new UsernameNotFoundException("用户名不存在");
}
}
}
2.2.2 MyAccessDecisionManager.java
package com.cloudtech.auth;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Iterator;
/**
*
* @ClassName: MyAccessDecisionManager
* @Description:
* @author wude
* @date 2019年1月11日
*
*/
@Service
public class MyAccessDecisionManager implements AccessDecisionManager {
// decide 方法是判定是否拥有权限的决策方法,
//authentication 是释CustomUserService中循环添加到 GrantedAuthority 对象中的权限信息集合.
//object 包含客户端发起的请求的requset信息,可转换为 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
//configAttributes 为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果,此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
if(null== configAttributes || configAttributes.size() <=0) {
return;
}
ConfigAttribute c;
String needRole;
for(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) {
c = iter.next();
needRole = c.getAttribute();
for(GrantedAuthority ga : authentication.getAuthorities()) {//authentication 为在注释1 中循环添加到 GrantedAuthority 对象中的权限信息集合
if(needRole.trim().equals(ga.getAuthority())) {
return;
}
}
}
throw new AccessDeniedException("no right");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
2.2.3 MyFilterSecurityInterceptor.java
package com.cloudtech.auth;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Service;
import java.io.IOException;
/**
*
* @ClassName: MyFilterSecurityInterceptor
* @Description:
* @author wude
* @date 2019年1月11日
*
*/
@Service
public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
@Autowired
private FilterInvocationSecurityMetadataSource securityMetadataSource;
@Autowired
public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) {
super.setAccessDecisionManager(myAccessDecisionManager);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
FilterInvocation fi = new FilterInvocation(request, response, chain);
invoke(fi);
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
//fi里面有一个被拦截的url
//里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
//再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够
InterceptorStatusToken token = super.beforeInvocation(fi);
try {
//执行下一个拦截器
fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
} finally {
super.afterInvocation(token, null);
}
}
@Override
public void destroy() {
}
@Override
public Class<?> getSecureObjectClass() {
return FilterInvocation.class;
}
@Override
public SecurityMetadataSource obtainSecurityMetadataSource() {
return this.securityMetadataSource;
}
}
2.2.4 MyInvocationSecurityMetadataSourceService.java
package com.cloudtech.auth;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;
import com.cloudtech.dao.PermissionMapper;
import com.cloudtech.entity.Permission;
import com.cloudtech.service.PermissionService;
/**
*
* @ClassName: MyInvocationSecurityMetadataSourceService
* @Description:
* @author wude
* @date 2019年1月11日
*
*/
@Service
public class MyInvocationSecurityMetadataSourceService implements
FilterInvocationSecurityMetadataSource {
@Autowired
private PermissionMapper permissionMapper;
@Autowired
private PermissionService permissionService;
private HashMap<String, Collection<ConfigAttribute>> map =null;
/**
* 加载权限表中所有权限
*/
public void loadResourceDefine(){
map = new HashMap<>();
Collection<ConfigAttribute> array;
ConfigAttribute cfg;
List<Permission> permissions = permissionService.findAll();
for(Permission permission : permissions) {
array = new ArrayList<>();
cfg = new SecurityConfig(permission.getName());
//此处只添加了用户的名字,其实还可以添加更多权限的信息,例如请求方法到ConfigAttribute的集合中去。此处添加的信息将会作为MyAccessDecisionManager类的decide的第三个参数。
array.add(cfg);
//用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value,
map.put(permission.getUrl(), array);
}
}
//此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
if(map ==null) loadResourceDefine();
//object 中包含用户请求的request 信息
HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
AntPathRequestMatcher matcher;
String resUrl;
for(Iterator<String> iter = map.keySet().iterator(); iter.hasNext(); ) {
resUrl = iter.next();
matcher = new AntPathRequestMatcher(resUrl);
if(matcher.matches(request)) {
return map.get(resUrl);
}
}
return null;
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
2.3 com.cloudtech.config
2.3.1 DruidConfig.java
package com.cloudtech.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid的监控
//1、配置一个管理后台的Servlet
@Bean
public ServletRegistrationBean<StatViewServlet> statViewServlet(){
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<StatViewServlet>(new StatViewServlet(), "/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123456");
initParams.put("allow","");//默认就是允许所有访问
initParams.put("deny","192.168.15.21");
bean.setInitParameters(initParams);
return bean;
}
//2、配置一个web监控的filter
@Bean
public FilterRegistrationBean<WebStatFilter> webStatFilter(){
FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<WebStatFilter>();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
2.3.2 MyBatisMapperScannerConfig.java
package com.cloudtech.config;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBatisMapperScannerConfig {
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
mapperScannerConfigurer.setBasePackage("com.cloudtech.dao");
return mapperScannerConfigurer;
}
}
2.3.3 WebSecurityConfig.java
package com.cloudtech.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.intercept.FilterSecurityInterceptor;
import com.cloudtech.auth.CustomUserService;
import com.cloudtech.auth.MyFilterSecurityInterceptor;
/**
*
* @ClassName: WebSecurityConfig
* @Description:
* @author wude
* @date 2019年1月10日
*
*/
@Configuration
@EnableWebSecurity // 注解开启Spring Security的功能
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyFilterSecurityInterceptor myFilterSecurityInterceptor;
@Autowired
private CustomUserService customUserService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 注入userDetailsService的实现类
auth.userDetailsService(customUserService).passwordEncoder(new BCryptPasswordEncoder()); // user
// Details
// Service验证
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/static/**").permitAll()
.anyRequest().authenticated() // 任何请求,登录后可以访问
.and().formLogin().loginPage("/login")
.failureUrl("/?error=true").permitAll() // 登录页面用户任意访问
.and().logout().permitAll(); // 注销行为任意访问
http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
}
}
2.4 com.cloudtech.controller
2.4.1 HomeController.java
package com.cloudtech.controller;
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.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.cloudtech.entity.Admin;
/**
*
* @ClassName: HomeController
* @Description:
* @author wude
* @date 2019年1月11日
*
*/
@Controller
public class HomeController {
@RequestMapping("/")
public String index(Model model) {
model.addAttribute("msg", "欢迎来到HOME页面,您拥有 ROLE_HOME 权限");
return "home";
}
@RequestMapping("/admin")
@ResponseBody
public String hello() {
return "hello admin";
}
@RequestMapping("/login")
public String login() {
return "login";
}
}
2.5 com.cloudtech.dao
2.5.1 AdminMapper.java
package com.cloudtech.dao;
import com.cloudtech.entity.Admin;
import tk.mybatis.mapper.common.Mapper;
public interface AdminMapper extends Mapper<Admin>{
}
2.5.2 PermissionMapper.java
package com.cloudtech.dao;
import java.util.List;
import com.cloudtech.entity.Permission;
import tk.mybatis.mapper.common.Mapper;
public interface PermissionMapper extends Mapper<Permission>{
/**
* 根据用户查询权限信息
* @param userId
* @return
*/
public List<Permission> findByAdminUserId(int userId);
}
2.6 com.cloudtech.demo
2.6.1 Demo2Application.java
package com.cloudtech.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication
@ComponentScan(value = {"com.cloudtech"})
@MapperScan(basePackages = "com.cloudtech.dao")
public class Demo2Application {
public static void main(String[] args) {
SpringApplication.run(Demo2Application.class, args);
}
}
2.7 com.cloudtech.entity
package com.cloudtech.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
public class Admin implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String username;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username == null ? null : username.trim();
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password == null ? null : password.trim();
}
}
package com.cloudtech.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
public class Permission implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String description;
private String url;
private Integer pid;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description == null ? null : description.trim();
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url == null ? null : url.trim();
}
public Integer getPid() {
return pid;
}
public void setPid(Integer pid) {
this.pid = pid;
}
}
package com.cloudtech.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
public class PermissionRole implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Integer roleId;
private Integer permissionId;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public Integer getPermissionId() {
return permissionId;
}
public void setPermissionId(Integer permissionId) {
this.permissionId = permissionId;
}
}
package com.cloudtech.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
public class Role implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
}
package com.cloudtech.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
public class RoleUser implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Column
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Integer userId;
private Integer roleId;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
}
2.8 com.cloudtech.mapper
2.8.1 PermissionMapper.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.cloudtech.dao.PermissionMapper">
<select id="findByAdminUserId" parameterType="int" resultType="com.cloudtech.entity.Permission">
select p.*
from admin u
LEFT JOIN role_user sru on u.id= sru.id
LEFT JOIN role r on sru.role_id=r.id
LEFT JOIN permission_role spr on spr.role_id=r.id
LEFT JOIN permission p on p.id =spr.permission_id
where u.id=#{userId}
</select>
</mapper>
2.9 com.cloudtech.service
package com.cloudtech.service;
import com.cloudtech.entity.Admin;
public interface AdminService {
/**
* 根据用户名判断用户是否存在
* @param username
* @return
*/
public Admin findByUserName(String username);
}
package com.cloudtech.service;
import java.util.List;
import com.cloudtech.entity.Permission;
public interface PermissionService {
/**
* 查询所有权限信息
* @return
*/
public List<Permission> findAll();
/**
*
* @param userId
* @return
*/
public List<Permission> findByAdminUserId(int userId);
}
2.9 com.cloudtech.service.impl
package com.cloudtech.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.cloudtech.dao.AdminMapper;
import com.cloudtech.entity.Admin;
import com.cloudtech.service.AdminService;
@Service
public class AdminServiceImpl implements AdminService {
@Autowired
private AdminMapper adminMapper;
@Override
public Admin findByUserName(String username) {
Admin admin = new Admin();
admin.setUsername(username);
admin = adminMapper.selectOne(admin);
return admin;
}
}
package com.cloudtech.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.cloudtech.dao.PermissionMapper;
import com.cloudtech.entity.Permission;
import com.cloudtech.service.PermissionService;
@Service
public class PermissionServiceImpl implements PermissionService {
@Autowired
private PermissionMapper permissionMapper;
@Override
public List<Permission> findAll() {
return permissionMapper.selectAll();
}
@Override
public List<Permission> findByAdminUserId(int userId) {
return permissionMapper.findByAdminUserId(userId);
}
}
application.yml
server:
port: 8080
spring:
datasource:
# 数据源基本配置
url: jdbc:mysql://XXX:3306/sb?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
username: XXX
password: XXX
driver-class-name: com.mysql.jdbc.Driver
#mybatis相关配置
mybatis:
#当mybatis的xml文件和mapper接口不在相同包下时
#需要用mapperLocations属性指定xml文件的路径。
#*是个通配符,代表所有的文件,**代表所有目录下
mapper-locations: classpath*:/com/cloudtech/mapper/*.xml
#指定bean所在包
#在mapper.xml中可以使用别名而不使用类的全路径名
type-aliases-package: com.cloudtech.web.entity
#通用mapper配置
mapper:
identity: MYSQL # 取主键的方式
before: false # 主键递增
not-empty: true # 按主键插入或更新时,是否判断字符串 != ''
style: camelhumpandlowercase # 实体类与表中字段的映射方式:驼峰转带下划线的小写格式
wrap-keyword: '{0}' # 自动配置关键字,配置后不需要使用 @Column 指定别名
safe-delete: true # 删除时必须设置查询条件
safe-update: true # 更新时必须设置查询条件
use-java-type: true # 是否映射Java基本数据类型
mappers: tk.mybatis.mapper.common.Mapper
#pagehelper分页插件
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security Example </title>
</head>
<body>
<!-- <p style="color: red" th:if="${error==true}">错误的帐号或密码</p> -->
<!-- 退出登陆会显示这句话 -->
<form th:action="@{/login}" method="post">
<div><label> 用户名 : <input type="text" name="username"/> </label></div>
<div><label> 密 码 : <input type="password" name="password"/> </label></div>
<div><input type="submit" value="登录"/></div>
</form>
<br/>
</body>
</html>
home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<meta content="text/html;charset=UTF-8"/>
<title sec:authentication="name"></title>
<link rel="stylesheet" th:href="@{css/bootstrap.min.css}" />
<style type="text/css">
body {
padding-top: 50px;
}
.starter-template {
padding: 40px 15px;
text-align: center;
}
</style>
</head>
<body>
<div sec:authorize="hasRole('ROLE_HOME')"> <!-- 用户类型为ROLE_ADMIN 显示 -->
<p class="bg-info" th:text="${msg}"></p>
</div>
</body>
</html>