SpringBoot基本操作(七)——SpringBoot整合Shiro权限管理(完整demo+界面)

2023-11-10

SpringBoot2.0笔记

(一)SpringBoot基本操作——环境搭建及项目创建(有demo)

(二)SpringBoot基本操作——使用IDEA打war包发布及测试

(三)SpringBoot基本操作——SpringBoot整合SpringDataJpa(有demo)

(四)SpringBoot基本操作——SpringBoot使用RedisTemplate整合Redis(有demo)

(五)SpringBoot基本操作——SpringBoot使用Jedis整合Redis(有demo)

(六)SpringBoot基本操作——SpringBoot使用Junit4单元测试(有demo)

(七)SpringBoot基本操作——SpringBoot整合Shiro权限管理(完整demo+界面)

 

这篇花了我挺久的时间做整合,因为包含了最完整的示例,很早之前我就准备做一个整合shiro的示例出来,为什么呢?因为我自己在开发中遇到了权限管理的需求,但是我在网上参考了很多大牛的文章,发现并没有一个完整的示例可以给出来的,所以我曾经自己手写了一个基于RBAC的权限管理功能,详见这里,这个模块目前也在我们的系统中运行着,但是随着系统越来越庞大,我发现这个东西没那么好用了,很多我并不需要加入权限的操作受限于白名单管理,维护变得麻烦起来,现在我以shiro替换掉了,以下我给出的这个demo是从我们目前的项目中抽离开出来的,配合我之前发布的springboot2.0基础demo做了精简整合,这个模块可以直接嵌入你的springboot项目系统中。本篇部分参考了纯洁的微笑大大的文章。

本文使用idea工具构建Springboot2.0+SpringMvc+Thymeleaf+SpringDataJPA+MySql+Shiro项目

GitHub地址:https://github.com/jwwam/springbootShiro.git

一、预览,这是一个怎样的项目

1.登录模块,包含注册功能,动态GIF验证码

2.管理员登录后台界面,包含权限模块最基本的用户管理、角色管理、资源管理。

3.用户管理包括最基本的增删改查+角色分配+状态修改

 4.添加用户界面

5.为用户分配角色

6.为角色分配资源

 7.资源的新建删除及修改

以上就是整个权限管理系统的界面浏览,下面将整理出完整的实现代码。

二、项目构建目录和maven依赖

 关键maven依赖

		<!-- shiro spring. -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>1.2.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.2.2</version>
		</dependency>
		<!-- shiro ehcache -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>1.2.2</version>
		</dependency>
		<dependency>
			<groupId>net.sf.json-lib</groupId>
			<artifactId>json-lib</artifactId>
			<version>2.4</version>
			<classifier>jdk15</classifier>
		</dependency>

三、Shiro配置

首先需要一个用户实体UserInfo.java

package com.springboot.demo.base.entity;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

@Table(name="user_info")
@SuppressWarnings("serial")
@Entity
public class UserInfo implements Serializable {
    @Id
    @GeneratedValue
    private Integer uid=1;
    @Column(unique =true)
    private String username;//帐号
    private String name;//名称(昵称或者真实姓名,不同系统不同定义)
    private String password; //密码;
    private String salt= "8d78869f470951332959580424d4bf4f";//加密密码的盐
    private int state=0;//用户状态,0:创建未认证(比如没有激活,没有输入验证码等等)--等待验证的用户 , 1:正常状态,2:用户被锁定.3: 已上传认证资料未审核. 4: 已上传认证资料审核未通过
    @Column(name= "create_date") //创建时间
    Date createDate = new Date();
    @Column(name= "update_date")//修改时间
    Date updateDate = new Date();
    @Column(name= "remarks")
    private String  remarks;//描述
    private String  phone;//手机
    private String  reason;//审核原因

    @ManyToMany(fetch= FetchType.EAGER)//立即从数据库中进行加载数据;
    @JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "uid") }, inverseJoinColumns ={@JoinColumn(name = "roleId") })
    private List<SysRole> roleList;// 一个用户具有多个角色

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }
    public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
	}

	public List<SysRole> getRoleList() {
        return roleList;
    }

    public void setRoleList(List<SysRole> roleList) {
        this.roleList = roleList;
    }

	public Date getCreateDate() {
		return createDate;
	}

	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}

	public Date getUpdateDate() {
		return updateDate;
	}

	public void setUpdateDate(Date updateDate) {
		this.updateDate = updateDate;
	}
	
	public String getRemarks() {
		return remarks;
	}

	public void setRemarks(String remarks) {
		this.remarks = remarks;
	}

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getReason() {
        return reason;
    }

    public void setReason(String reason) {
        this.reason = reason;
    }

    /**
     * 密码盐.
     * @return
     */
    public String getCredentialsSalt(){
        return this.username+this.salt;
    }
    //重新对盐重新进行了定义,用户名+salt,这样就更加不容易被破解
    
    
    
}

添加ShiroConfig.java

这里需要配置shiro的过滤规则

package com.springboot.demo.base.config;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

@Configuration
public class ShiroConfig {
	@Bean
	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		System.out.println("ShiroConfiguration.shirFilter()");
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		//拦截器.
		Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
		// 配置不会被拦截的链接 顺序判断
		//filterChainDefinitionMap.put("/static/**", "anon");
		//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
		filterChainDefinitionMap.put("/logout", "logout");
		//<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
		//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
		filterChainDefinitionMap.put("/static/templates/**", "authc");
		// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
		shiroFilterFactoryBean.setLoginUrl("/login/loginUser");
		// 登录成功后要跳转的链接
		shiroFilterFactoryBean.setSuccessUrl("/login/home");

		//未授权界面;
		shiroFilterFactoryBean.setUnauthorizedUrl("/base/error");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}

	/**
	 * 凭证匹配器
	 * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
	 * )
	 * @return
	 */
	@Bean
	public HashedCredentialsMatcher hashedCredentialsMatcher(){
		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
		hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
		hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));
		return hashedCredentialsMatcher;
	}

	@Bean
	public ShiroRealm myShiroRealm(){
		ShiroRealm myShiroRealm = new ShiroRealm();
		myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
		return myShiroRealm;
	}


	@Bean
	public SecurityManager securityManager(){
		DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
		securityManager.setRealm(myShiroRealm());
		return securityManager;
	}

	/**
	 *  开启shiro aop注解支持.
	 *  使用代理方式;所以需要开启代码支持;
	 * @param securityManager
	 * @return
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}

	@Bean(name="simpleMappingExceptionResolver")
	public SimpleMappingExceptionResolver
	createSimpleMappingExceptionResolver() {
		SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
		Properties mappings = new Properties();
		mappings.setProperty("DatabaseException", "/base/databaseError");//数据库异常处理
		mappings.setProperty("UnauthorizedException","/base/error");
		r.setExceptionMappings(mappings);  // None by default
		//r.setDefaultErrorView("error");    // No default
		r.setDefaultErrorView("/base/login");    // 访问错误,直接访问登录页面
		r.setExceptionAttribute("ex");     // Default is "exception"
		//r.setWarnLogCategory("example.MvcLogger");     // No default
		return r;
	}




}

ShiroRealm.java

这里主要进行用户身份的校验

package com.springboot.demo.base.config;

import javax.annotation.Resource;

import com.springboot.demo.base.entity.SysPermission;
import com.springboot.demo.base.entity.SysRole;
import com.springboot.demo.base.entity.UserInfo;
import com.springboot.demo.base.service.UserInfoService;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

public class ShiroRealm extends AuthorizingRealm {
    @Resource
    private UserInfoService userInfoService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        UserInfo userInfo  = (UserInfo)principals.getPrimaryPrincipal();
        for(SysRole role:userInfo.getRoleList()){
            authorizationInfo.addRole(role.getRole());
            for(SysPermission p:role.getPermissions()){
                authorizationInfo.addStringPermission(p.getPermission());
            }
        }
        //CacheUntil.setCacheTree(authorizationInfo);
        return authorizationInfo;
    }

    /*主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        System.out.println("ShiroRealm.doGetAuthenticationInfo()");
        //获取用户的输入的账号.
        String username = (String)token.getPrincipal();
        //通过username从数据库中查找 User对象,如果找到,没找到.
        //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
        UserInfo userInfo = userInfoService.findByUsername(username);
        if(userInfo == null){
            return null;
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                userInfo, //用户名
                userInfo.getPassword(), //密码
                ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }

}

LoginController.java

loginUser方法进行登录信息的校验,根据shiro返回的不同异常进行提示

package com.springboot.demo.base.controller;

import com.springboot.demo.base.entity.UserInfo;
import com.springboot.demo.base.utils.Captcha;
import com.springboot.demo.base.utils.GifCaptcha;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.io.IOException;
import java.util.Random;

@Controller
@RequestMapping("/login")
public class LoginController extends  BaseController{
	
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());

	/**
	 * 获取验证码(Gif版本)
	 * @param response
	 */
	@RequestMapping(value="getGifCode",method = RequestMethod.GET)
	public void getGifCode(HttpServletResponse response,HttpServletRequest request){
		try {
			response.setHeader("Pragma", "No-cache");
			response.setHeader("Cache-Control", "no-cache");
			response.setDateHeader("Expires", 0);
			response.setContentType("image/gif");
			/**
			 * gif格式动画验证码
			 * 宽,高,位数。
			 */
			HttpSession session = request.getSession(true);

			Captcha captcha = new GifCaptcha(146,33,4);
			/* 输出 */
			captcha.out(response.getOutputStream());
			String vcodeText = captcha.text().toLowerCase();
			//存入Session
			session.setAttribute("_code",vcodeText);
			logger.info("保存vcode:"+vcodeText);

			System.out.println("------"+session.getAttribute("_code"));

		} catch (Exception e) {
			e.printStackTrace();
			System.err.println("获取验证码异常:"+e.getMessage());
		}
	}


	@RequestMapping("")
    public String index(){
    	
    	logger.info("初始化登录页面....");
        return"/base/login";
        
    }
	@RequestMapping("/home")
	public String home(HttpServletResponse response){
		UserInfo ui = this.getCurrentUser();
		if( ui == null ){
			try {
				response.sendRedirect("../login");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		logger.info("初始化home页面....");
		return"/base/home";

	}
    
    @RequestMapping("/loginUser")
    public String loginUser(HttpServletRequest request,String username,String password,String vcode) {

		    HttpSession session = request.getSession();
			//转化成小写字母
			vcode = vcode.toLowerCase();
			String v = (String)session.getAttribute("_code");//还可以读取一次后把验证码清空,这样每次登录都必须获取验证码;
		    logger.info("获取保存vcode:"+v);
	    	logger.info("验证vcode:"+vcode);
			if(!vcode.equals(v)){
				logger.info("对用户[" + username + "]验证码不通过");
				request.setAttribute("message", "验证码不正确");
				return "/base/login";//返回登录页面
			}

        	logger.info("进行账号"+username+",密码验证"+password+".....");
        	UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);
        	Subject subject = SecurityUtils.getSubject();
    		try {  
        		subject.login(usernamePasswordToken);   //完成登录
        		UserInfo user=(UserInfo) subject.getPrincipal();
        		session.setAttribute("user", user);
        		session.setAttribute("clickId","home");
        		return "/base/loadHome";
	        }catch(UnknownAccountException uae){  
	            logger.info("对用户[" + username + "]进行登录验证..验证未通过,未知账户");  
	            request.setAttribute("message", "未知账户");  
	            return "/base/login";//返回登录页面
	        }catch(IncorrectCredentialsException ice){  
	            logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");  
	            request.setAttribute("message", "密码不正确");  
	            return "/base/login";//返回登录页面
	        }catch(LockedAccountException lae){  
	            logger.info("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");  
	            request.setAttribute("message", "账户已锁定");
	            return "/base/login";//返回登录页面
	        }catch(ExcessiveAttemptsException eae){  
	            logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");  
	            request.setAttribute("message", "用户名或密码错误次数过多");
	            return "/base/login";//返回登录页面
	        }catch(AuthenticationException ae){  
	            //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景  
	            logger.info("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");
	            ae.printStackTrace();  
	            request.setAttribute("message", "用户名或密码不正确");  
	            return "/base/login";//返回登录页面
	        }  
        
    }
    
    @RequestMapping("/logOut")
    public String logOut(HttpSession session) {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        session.removeAttribute("user");
        return "/base/login";
    }

    @RequestMapping("/403")
    public String unauthorizedRole(){
        System.out.println("------没有权限-------");
        return "403";
    }


	/**
	 * 给定范围获得随机颜色
	 * @param fc
	 * @param bc
	 * @return
	 */
	private Color getRandColor(int fc, int bc) {
		Random random = new Random();
		if (fc > 255)
			fc = 255;
		if (bc > 255)
			bc = 255;
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);
	}
	


}

在ShiroConfig.java中我们开启了shiro鉴权的aop支持,下面我们看如何使用它,关于用户UserInfo的增删改查及service、dao不再列出。

新建StudentController.java,配置一个访问路径RequestMapping为student/studentView,在方法上加入shiro鉴权注解@RequiresPermissions("student:view"),这里注意,在界面上的配置如下图,和权限字符串保持一致即可。

这样我们就添加了一个学生管理菜单,后面将其分配给不同角色,那么属于该角色的用户将能够访问student/studentView的内容。

注意application.properties需配置静态资源的路径,否则会获取不到静态文件。

#数据源
spring.datasource.url=jdbc:mysql://localhost:3306/demo_test?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true
spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

spring.jpa.properties.hibernate.hbm2ddl.auto=update

#热部署生效
spring.devtools.restart.enabled=true

#mvc静态文件配置
#/css/**,/js/**,/componets/**,/images/**
spring.mvc.static-path-pattern=/**
spring.resources.static-locations=classpath:/static/,classpath:/templates/

最后给出完整的表结构和pom包

/*
Navicat MySQL Data Transfer

Source Server         : localhost
Source Server Version : 50717
Source Host           : localhost:3306
Source Database       : demo_test

Target Server Type    : MYSQL
Target Server Version : 50717
File Encoding         : 65001

Date: 2018-09-01 20:17:12
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for hibernate_sequence
-- ----------------------------
DROP TABLE IF EXISTS `hibernate_sequence`;
CREATE TABLE `hibernate_sequence` (
  `next_val` bigint(20) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of hibernate_sequence
-- ----------------------------
INSERT INTO `hibernate_sequence` VALUES ('10');
INSERT INTO `hibernate_sequence` VALUES ('10');
INSERT INTO `hibernate_sequence` VALUES ('10');

-- ----------------------------
-- Table structure for sys_permission
-- ----------------------------
DROP TABLE IF EXISTS `sys_permission`;
CREATE TABLE `sys_permission` (
  `id` int(11) NOT NULL,
  `available` bit(1) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `number_sort` datetime DEFAULT NULL,
  `parent_id` bigint(20) DEFAULT NULL,
  `parent_ids` varchar(255) DEFAULT NULL,
  `permission` varchar(255) DEFAULT NULL,
  `resource_type` enum('menu','button') DEFAULT NULL,
  `url` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_permission
-- ----------------------------
INSERT INTO `sys_permission` VALUES ('1', '\0', '用户管理', '2018-06-25 11:30:51', '0', '0/', 'userInfo:view', 'menu', 'userInfo/userView');
INSERT INTO `sys_permission` VALUES ('2', '\0', '用户添加', '2018-06-25 11:34:51', '1', '0/1', 'userInfo:add', 'button', 'userInfo/userAdd');
INSERT INTO `sys_permission` VALUES ('3', '\0', '用户禁用', '2018-06-25 11:35:51', '1', '0/1', 'userInfo:del', 'button', 'userInfo/updateState');
INSERT INTO `sys_permission` VALUES ('4', '\0', '角色管理', '2018-06-25 11:40:51', '0', null, 'roleInfo:view', 'menu', 'roleInfo/roleView');
INSERT INTO `sys_permission` VALUES ('5', '\0', '资源管理', '2018-06-25 11:40:51', '0', null, 'sysPermission:view', 'menu', 'sysPermission/permissionView');
INSERT INTO `sys_permission` VALUES ('9', '\0', '学生管理', '2018-09-01 20:08:46', '0', null, 'student:view', 'menu', 'student/studentView');

-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
  `id` int(11) NOT NULL,
  `available` bit(1) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  `role` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('2', '\0', '新注册用户', '新用户');
INSERT INTO `sys_role` VALUES ('1', '\0', '管理员', 'admin');

-- ----------------------------
-- Table structure for sys_role_permission
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_permission`;
CREATE TABLE `sys_role_permission` (
  `permission_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  KEY `FK9q28ewrhntqeipl1t04kh1be7` (`role_id`),
  KEY `FKomxrs8a388bknvhjokh440waq` (`permission_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_role_permission
-- ----------------------------
INSERT INTO `sys_role_permission` VALUES ('5', '1');
INSERT INTO `sys_role_permission` VALUES ('4', '1');
INSERT INTO `sys_role_permission` VALUES ('1', '1');
INSERT INTO `sys_role_permission` VALUES ('3', '1');
INSERT INTO `sys_role_permission` VALUES ('2', '1');
INSERT INTO `sys_role_permission` VALUES ('6', '1');

-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
  `uid` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  KEY `FKhh52n8vd4ny9ff4x9fb8v65qx` (`role_id`),
  KEY `FKgkmyslkrfeyn9ukmolvek8b8f` (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES ('1', '1');

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` varchar(255) NOT NULL,
  `create_date` datetime DEFAULT NULL,
  `update_date` datetime DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `name` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('56a514fc657d4dc09cb12b09f39d6846', '2018-08-28 01:42:20', '2018-08-28 01:42:20', '0', '老王的儿子');
INSERT INTO `user` VALUES ('c9e56bc8d15c45bb838a63786f931908', '2018-08-28 15:07:32', null, '25', '老王');
INSERT INTO `user` VALUES ('739086403d084de397282e8173d29f73', '2018-08-28 15:35:44', null, '22', '老王2');
INSERT INTO `user` VALUES ('c6bae69dad8c4b538ad4bafd435837c3', '2018-08-28 16:46:02', null, '18', '老王4');

-- ----------------------------
-- Table structure for user_info
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info` (
  `uid` int(11) NOT NULL,
  `create_date` datetime DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `phone` varchar(255) DEFAULT NULL,
  `reason` varchar(255) DEFAULT NULL,
  `remarks` varchar(255) DEFAULT NULL,
  `salt` varchar(255) DEFAULT NULL,
  `state` int(11) NOT NULL,
  `update_date` datetime DEFAULT NULL,
  `username` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`uid`),
  UNIQUE KEY `UK_f2ksd6h8hsjtd57ipfq9myr64` (`username`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES ('1', '2018-06-23 17:07:40', '管理员', 'd3c59d25033dbf980d29554025c23a75', null, null, null, '8d78869f470951332959580424d4bf4f', '1', '2018-08-31 15:56:33', 'admin');
INSERT INTO `user_info` VALUES ('3', '2018-08-31 16:13:53', '张三', '79332ad51f315fdcdaaa0394c46ffcd7', null, null, '', '8d78869f470951332959580424d4bf4f', '0', '2018-08-31 16:13:53', 'zhangsan');
<?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>

	<groupId>com.springboot</groupId>
	<artifactId>springbootJpa</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<name>springbootJpa</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.4.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<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-starter-tomcat</artifactId>
			<!--<scope>provided</scope>-->
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.hibernate</groupId>
					<artifactId>hibernate-entitymanager</artifactId>
				</exclusion>
				<exclusion>
					<groupId>org.hibernate</groupId>
					<artifactId>hibernate-core</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>5.2.10.Final</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-mail</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>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- shiro spring. -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>1.2.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.2.2</version>
		</dependency>
		<!-- shiro ehcache -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>1.2.2</version>
		</dependency>
		<dependency>
			<groupId>net.sf.json-lib</groupId>
			<artifactId>json-lib</artifactId>
			<version>2.4</version>
			<classifier>jdk15</classifier>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>
	</dependencies>

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


</project>

全文完,2018/9/1

写博文不易,转载请注明出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot基本操作(七)——SpringBoot整合Shiro权限管理(完整demo+界面) 的相关文章

随机推荐

  • Android TV RecyclerView 焦点处理及获取焦点的Item保持在中间

    原生RecyclerView 在Tv中的焦点处理很不好 经常找不到焦点或者焦点丢失 原因是因为当item未显示时即未加载时时不能获取焦点的 所以当我们按上下键时经常丢失焦点或者焦点乱跳 要解决这个问题我们必须要手动控制RecyclerVie
  • JavaScript 输入内容表单规则验证

    1 电子邮箱格式 function emailCheck data let str a zA Z0 9 a zA Z0 9 a zA Z0 9 0 61 a zA Z0 9 a zA Z0 9 a zA Z0 9 0 61 a zA Z0
  • Mybatis框架全面详解

    MyBatis的基本使用 第一章 MyBatis的概念 第二章 MyBtais的基本使用 2 1 环境的搭建 2 1 1 物理建模 2 1 2 逻辑建模 2 1 3 搭建框架开发环境 2 1 3 1 junit框架 2 1 3 2 log4
  • 前端笔记之JavaScript(三)关于条件判断语句、循环语句那点事

    一 条件分支语句 条件分支语句 也叫作条件判断语句 就是根据某种条件执行某些语句 不执行某些语句 JS中有三种语法是可以表示条件分支的 1 1 if else 条件分支的主力语法 这个主力语法能够书写所有的条件分支语句 也就是说 一会儿学s
  • DFS 显示n个数中选取i(0~n)个数的情况

    include
  • 面试之JVM的储存空间

    Java8之后 取消了整个永久代区域 取而代之的是元空间 运行时常量池和静态常量池存放在元空间中 而字符串常量池依然存放在堆中 JVM允许时数据区 程序计数器的特点以及作用 1 程序计数器 是一块较小的内存空间 2 是当前线程所指向的字节码
  • Maven 快照(SNAPSHOT)

    一个大型的软件应用通常包含多个模块 并且通常的场景是多个团队开发同一应用的不同模块 举个例子 设想一个团队开发应用的前端 项目为 app ui app ui jar 1 0 而另一个团队开发应用的后台 使用的项目是 data service
  • 【异常】java: 警告: 源发行版 11 需要目标发行版 11

    写在前面 笔者遇到的问题比较极端 在阅读之前建议检查是否是项目结构中语言级别和jdk版本不匹配的问题 确认并非语言级别级别问题再阅读以下 先说结论 idea 的 配置文件iml 与项目中 配置 的jdk版本不一致 排查 iml 文件 检查L
  • CSS3设置flex,图片的高度被自适应了

    如图所示 因为给最内存的图片宽度设置了width 100 会寻找上一级的高度 上一级没设置会自动寻找父元素 父元素的宽度为整个页面 所以img宽度为父元素宽度的6分之一 自然高度也会自适应变小了 设置width 600自然就能恢复高度了
  • PHP+JavaScript+HTML实现上传PDF和浏览PDF课件

    在寒假简单制作PHP网站时 需要实现在线浏览PDF和上传PDF的简单功能 下面就简单介绍下该功能 实现效果如下图所示 1 当用户登录后 点击 上传课件 超链接可以实现隐藏和显示上传table的功能 2 当用户选择上传的课件后 PDF上传至本
  • Mybatis -maven插件方式自动生成pojo,mapper文件代码(generatorConfig.xml)

    1 新建springboot工程 添加maven依赖
  • python为字体添加上下标

    添加上标 添加下标 举例 import numpy as np import matplotlib pyplot as plt t np linspace 0 10 1000 y np sin t plt plot t y plt xlab
  • 基于线性表的图书管理系统(java)

    目录 1 简介 2 代码 1 ManageSystem类 2 book类 3 测试程序运行结果截图 1 登录和创建 2 输出 3 查找 4 插入 5 删除 6 修改 7 排序 8 计数 9 导出 10 读入 11 菜单 4 存在的问题与思考
  • 零阶矩、一阶矩、二阶矩、三阶矩

    参考 Moment mathematics Wikipedia 此处截取其中的一段 In mathematics a moment is a specific quantitative measure used in both mechan
  • 记一次从web到内网的渗透

    记一次从web到内网的渗透 拓扑图 环境介绍 现在有三台机器 分别为target1 target2 target3 里面分别有三个flag 每个flag的分值不同 需要通过拿下一个已知IP target1 进而向内网里面进行渗透 最终要成功
  • 字符设备驱动程序

    字符设备驱动程序 下面以一个简单的例子来讲解下字符设备驱动程序 首先需要有内核环境 Linux下的设备驱动程序被组织为一组完成不同任务的函数的集合 通过这些函数使得Windows的设备操作犹如文件一般 在应用程序看来 硬件设备只 是一个设备
  • 淘宝客app源码如何选择技术栈?

    选择技术栈是开发淘宝客App的重要决策 它将直接影响到开发效率和产品质量 首先 选择技术栈的时候需要考虑淘宝客App的功能和需求 淘宝客App作为一个电商平台 涉及到用户登录 商品展示 下单支付 优惠券等功能 因此选择的技术栈需要支持这些功
  • linux篇【12】:网络套接字<中序>——tcp

    目录 查看TCP网络服务器情况和端口使用情况 netstat nltp 一 TCP套接字接口 1 inet aton 和inet addr一样 换一种方式而已 2 listen 把套接字设置为监听状态 3 服务器获取客户端的连接 accep
  • c++中整形输入逗号_很重要的收集 --- 关于c++的各种输入(包括istream_iterator结合逗号分隔)...

    最近又开始刷题了 在这个过程中 我不断地发现一个问题 就是不同的题目会有不同的输入要求 而如果用c 这么繁复的语言在刷题的时候 有时候光是一个输入就会把所有的时间都消耗得一干二净 因此我在这里设立一篇文章用来记录不同的输入方式 本篇文章采取
  • SpringBoot基本操作(七)——SpringBoot整合Shiro权限管理(完整demo+界面)

    SpringBoot2 0笔记 一 SpringBoot基本操作 环境搭建及项目创建 有demo 二 SpringBoot基本操作 使用IDEA打war包发布及测试 三 SpringBoot基本操作 SpringBoot整合SpringDa