1.基本知识
四大基石----身份验证,授权,会话管理,加密
1.Authentication:身份认证/登录,验证用户是不是拥有相应的身份;
2.Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
3.Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;
4.Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
除以上功能外,shiro还提供了很多扩展如下
Web Support:Web支持,可以非常容易的集成到Web环境;
Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
Testing:提供测试支持;
Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
记住一点,Shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供;然后通过相应的接口注入给Shiro即可。
2.过滤器权限拦截器
过滤器简称
对应的java类
anon | 例子/admins/**=anon | 没有参数,表示可以匿名使用 |
---|---|---|
authc | 例子/admins/user/**=authc | 表示需要认证(登录)才能使用,没有参数 |
roles(角色) | 例子/admins/user/**=roles[admin] | 参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。 |
perms(权限) | 例子/admins/user/*=perms[user:add:] | 参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/=perms["user:add:,user:modify:"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。 |
rest | 例子/admins/user/**=rest[user] | 根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。 |
port | 例子/admins/user/**=port[8081] | 当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。 |
authcBasic | 例如/admins/user/**=authcBasic | 没有参数表示httpBasic认证 |
ssl | 例子/admins/user/**=ssl | 没有参数,表示安全的url请求,协议为https |
user | 例如/admins/user/**=user | 没有参数表示必须存在用户,当登入操作时不做检查 |
默认过滤器名 | 指定类名 | 说明 |
---|---|---|
认证过滤器 | ||
authc | FormAuthenticationFilter—基于表单的过滤器; | 如“/**=authc”没有登录会跳到相应页登录;主要属性:usernameParam:表单提交的用户名参数;passwordParam:表单提交的密码参数;rememberMeParam:表单提交叫记住我;loginUrl:登录页地址;successUrl登录成功后的默认重定向地址;failureKeyAttribute:登录失败后错误信息存储key(shiroLoginFailure); |
authc Basic | BasicHttpAuthenticationFilter—HTTP身份验证过滤器 | 主要属性:applicationName:弹出登录框显示的信息(application); |
logout | LogoutFilter—退出过滤器 | 主要属性:redirectUrl:退出成功后重定向的地址(/);示例“/logout=logout” |
user | UserFilter—用户过滤器 | 用户已经身份验证/记住我登录的都可;示例 “/**=user” |
anon | AnonymousFilter—匿名过滤器 | 即不需要登录即可访问;一般用于静态资源过滤;示例 “/static/**=anon” |
授权过滤器 | ||
roles | RolesAuthorizationFilter—角色授权过滤器 | 验证用户是否拥有所有角色;主要属性:loginUrl:登录页面地址(/login.jsp);unauthorizedUrl:未授权后重定向的地址;示例“/admin/**=roles[admin]” |
perms | PermissionsAuthorizationFilter—权限授权过滤器 | 验证用户是否拥有所有权限;属性和 roles 一样;示例“/user/**=perms["user:create"]” |
host | HostFilter—即主机过滤器 | 比如其提供了属性:authorizedIps:已授权的 ip 地址,deniedIps:表示拒绝的 ip 地址;不过目前还没有完全实现,不可用。 |
port | PortFilter—端口过滤器 | 主要属性:port(80):可以通过的端口;示例 “/test= port[80]”,如果用户访问该页面是非 80,将自动将请求端口改为80并重定向到该80端口,其他路径/参数等都一样 |
rest | HttpMethodPermissionFilter—rest风格过滤器 | 自动根据请求方法构建权限字符串(GET=read, POST=create,PUT=update,DELETE=delete,HEAD=read,TRACE=read,OPTIONS=read, MKCOL=create)构建权限字符串;示例“/users=rest[user]”,会自动拼出“user:read,user:create,user:update,user:delete”权限字符串进行权限匹配(所有都得匹配,isPermittedAll); |
ssl | slFilter—SSL过滤器 | 只有请求协议是https才能通过;否则自动跳转会 https 端口(443);其他和port过滤器一样; |
其它过滤器 | ||
noSessionCreati on | NoSessionCreationFilter—不创建会话过滤器 | 调用 subject.getSession(false)不会有什么问题,但是如果subject.getSession(true)将抛出DisabledSessionException 异常; |
3.引入shiro依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.2</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- lombok插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<!-- swagger2 API管理测试 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!-- springboot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- jpa依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
4.yml配置文件
#用的是mysql8.0版本
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC
username: root
password: root
jpa:
hibernate:
ddl-auto: update #指定为update,每次启动项目检测表结构有变化的时候会新增字段,表不存在时会新建,如果指定create,则每次启动项目都会清空数据并删除表,再新建
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl #按字段名字建表
#implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl #驼峰自动映射为下划线格式
show-sql: true # 默认false,在日志里显示执行的sql语句
database: mysql
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
5.Realm配置
import com.example.shiro.entity.Permission;
import com.example.shiro.entity.Role;
import com.example.shiro.entity.User;
import com.example.shiro.service.UserService;
import org.apache.shiro.authc.*;
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;
import javax.annotation.Resource;
public class MyShiroRealm extends AuthorizingRealm {
@Resource
private UserService userService;
/**
* 身份认证:验证用户输入的账号和密码是否正确。
* */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取用户输入的账号
String userName = (String) token.getPrincipal();
//通过username从数据库中查找 User对象.
//实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
User user = userService.findByUserName(userName);
if (user == null) {
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user,//这里传入的是user对象,比对的是用户名,直接传入用户名也没错,但是在授权部分就需要自己重新从数据库里取权限
user.getPassword(),//密码
ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
getName()//realm name
);
return authenticationInfo;
}
/**
* 权限信息
* */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//如果身份认证的时候没有传入User对象,这里只能取到userName
//也就是SimpleAuthenticationInfo构造的时候第一个参数传递需要User对象
User user = (User)principals.getPrimaryPrincipal();
for(Role role : user.getRoleList()){
//添加角色
authorizationInfo.addRole(role.getRole());
for(Permission p:role.getPermissions()){
//添加权限
authorizationInfo.addStringPermission(p.getPermission());
}
}
return authorizationInfo;
}
}
6.Shiro配置
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
@Configuration
public class ShiroConfig {
//将自己的验证方式加入容器
@Bean
MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myShiroRealm;
}
//权限管理,配置主要是Realm的管理认证
@Bean
DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(myShiroRealm());
return manager;
}
//凭证匹配器(密码校验交给Shiro的SimpleAuthenticationInfo进行处理)
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));
return hashedCredentialsMatcher;
}
// Filter工厂,设置对应的过滤条件和跳转条件
@Bean
ShiroFilterFactoryBean shiroFilterFactoryBean() {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
bean.setSecurityManager(securityManager());
Map<String, String> filterMap = new HashMap<String, String>();
// 登出
filterMap.put("/logout", "logout");
// swagger
filterMap.put("/swagger**/**", "anon");
filterMap.put("/webjars/**", "anon");
filterMap.put("/v2/**", "anon");
// 对所有用户认证
filterMap.put("/**", "authc");
// 登录
bean.setLoginUrl("/login");
// 首页
bean.setSuccessUrl("/index");
// 未授权页面,认证不通过跳转
bean.setUnauthorizedUrl("/403");
bean.setFilterChainDefinitionMap(filterMap);
return bean;
}
//开启shiro aop注解支持.
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
//shiro注解模式下,登录失败或者是没有权限都是抛出异常,并且默认的没有对异常做处理,配置一个异常处理
@Bean(name="simpleMappingExceptionResolver")
public SimpleMappingExceptionResolver
createSimpleMappingExceptionResolver() {
SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
mappings.setProperty("UnauthorizedException","/403");
r.setExceptionMappings(mappings); // None by default
r.setDefaultErrorView("error"); // No default
r.setExceptionAttribute("exception"); // Default is "exception"
return r;
}
}
7.swagger2配置
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build();
}
private static ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("API文档")
.description("Swagger API 文档")
.version("1.0")
.contact(new Contact("name..", "url..", "email.."))
.build();
}
}
8.其他类
8.1创建实体类
User
import lombok.Getter;
import lombok.Setter;
import org.springframework.format.annotation.DateTimeFormat;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Entity
@Getter
@Setter
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
@Column(nullable = false, unique = true)
private String userName; //登录用户名
@Column(nullable = false)
private String name;//名称(昵称或者真实姓名,根据实际情况定义)
@Column(nullable = false)
private String password;
private String salt;//加密密码的盐
private byte state;//用户状态,0:创建未认证(比如没有激活,没有输入验证码等等)--等待验证的用户 , 1:正常状态,2:用户被锁定.
@ManyToMany(fetch= FetchType.EAGER)//立即从数据库中进行加载数据;
@JoinTable(name = "UserRole", joinColumns = { @JoinColumn(name = "userId") }, inverseJoinColumns ={@JoinColumn(name = "roleId") })
private List<Role> roleList;// 一个用户具有多个角色
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm")
private LocalDateTime createTime;//创建时间
@DateTimeFormat(pattern = "yyyy-MM-dd")
private LocalDate expiredDate;//过期日期
private String email;
/**密码盐. 重新对盐重新进行了定义,用户名+salt,这样就不容易被破解 */
public String getCredentialsSalt(){
return this.userName+this.salt;
}
}
说明:
这里使用@Getter,@Setter注解,不能使用@Data注解,因为实体使用了jpa的@oneToMany ,加载方式为lazy,在主表查询时关联表未加载,而主表使用@Data后会实现带关联表属性的hashCode和equals等方法。在运行过程中调用关联表数据时会显示异常 java.lang.stackoverflowerror。
Role
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.List;
@Entity
@Getter
@Setter
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long roleId; // 编号
@Column(nullable = false, unique = true)
private String role; // 角色标识程序中判断使用,如"admin",这个是唯一的:
private String description; // 角色描述,UI界面显示使用
private Boolean available = Boolean.TRUE; // 是否可用,如果不可用将不会添加给用户
//角色 -- 权限关系:多对多关系;
@ManyToMany(fetch= FetchType.EAGER)
@JoinTable(name="RolePermission",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="permissionId")})
private List<Permission> permissions;
// 用户 - 角色关系定义;
@ManyToMany
@JoinTable(name="UserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="userId")})
private List<User> users;// 一个角色对应多个用户
}
Permission
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.List;
@Entity
@Getter
@Setter
public class Permission {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long permissionId;//主键.
@Column(nullable = false)
private String permissionName;//名称.
@Column(columnDefinition="enum('menu','button')")
private String resourceType;//资源类型,[menu|button]
private String url;//资源路径.
private String permission; //权限字符串,menu例子:role:*,button例子:role:create,role:update,role:delete,role:view
private Long parentId; //父编号
private String parentIds; //父编号列表
private Boolean available = Boolean.TRUE;
//角色 -- 权限关系:多对多关系;
@ManyToMany(fetch= FetchType.EAGER)
@JoinTable(name="RolePermission",joinColumns={@JoinColumn(name="permissionId")},inverseJoinColumns={@JoinColumn(name="roleId")})
private List<Role> roles;
}
LoginResult
import lombok.Data;
@Data
public class LoginResult {
private boolean isLogin = false;
private String result;
}
8.2Dao类
BaseRepository
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import java.io.Serializable;
@NoRepositoryBean
public interface BaseRepository<T, I extends Serializable> extends PagingAndSortingRepository<T, I>, JpaSpecificationExecutor<T> {
}
UserRepository
import com.example.shiro.entity.User;
public interface UserRepository extends BaseRepository<User,Long> {
User findByUserName(String userName);
}
8.3Service
LoginService
import com.example.shiro.model.LoginResult;
public interface LoginService {
LoginResult login(String userName, String password);
void logout();
}
UserService
import com.example.shiro.entity.User;
public interface UserService {
User findByUserName(String userName);
}
8.4Service.impl
LoginServiceImpl
import com.example.shiro.model.LoginResult;
import com.example.shiro.repository.UserRepository;
import com.example.shiro.service.LoginService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;
@Service
public class LoginServiceImpl implements LoginService {
@Override
public LoginResult login(String userName, String password) {
LoginResult loginResult = new LoginResult();
if (userName == null || userName.isEmpty()) {
loginResult.setLogin(false);
loginResult.setResult("用户名为空");
return loginResult;
}
String msg = "";
// 1、获取Subject实例对象
Subject currentUser = SecurityUtils.getSubject();
// // 2、判断当前用户是否登录
// if (currentUser.isAuthenticated() == false) {
//
// }
// 3、将用户名和密码封装到UsernamePasswordToken
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
// 4、认证
try {
currentUser.login(token);// 传到MyAuthorizingRealm类中的方法进行认证
Session session = currentUser.getSession();
session.setAttribute("userName", userName);
loginResult.setLogin(true);
return loginResult;
//return "/index";
} catch (UnknownAccountException e) {
e.printStackTrace();
msg = "UnknownAccountException -- > 账号不存在:";
} catch (IncorrectCredentialsException e) {
msg = "IncorrectCredentialsException -- > 密码不正确:";
} catch (AuthenticationException e) {
e.printStackTrace();
msg = "用户验证失败";
}
loginResult.setLogin(false);
loginResult.setResult(msg);
return loginResult;
}
@Override
public void logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
}
}
UserServiceImpl
import com.example.shiro.entity.User;
import com.example.shiro.repository.UserRepository;
import com.example.shiro.service.UserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserRepository userRepository;
@Override
public User findByUserName(String userName) {
return userRepository.findByUserName(userName);
}
}
8.5controller
LoginController
import com.example.shiro.entity.User;
import com.example.shiro.model.LoginResult;
import com.example.shiro.service.LoginService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class LoginController {
@Resource
private LoginService loginService;
@GetMapping(value = "/login")
public String login() {
return "登录页";
}
@PostMapping(value = "/login")
public String login(@RequestBody User user) {
System.out.println("login()");
String userName = user.getUserName();
String password = user.getPassword();
LoginResult loginResult = loginService.login(userName,password);
if(loginResult.isLogin()){
return "登录成功";
} else {
return "登录失败:" + loginResult.getResult();
}
}
@GetMapping(value = "/index")
public String index() {
return "主页";
}
@GetMapping(value = "/logout")
public String logout() {
return "退出";
}
@GetMapping("/403")
public String unauthorizedRole(){
return "没有权限";
}
}
UserController
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
//用户查询
@GetMapping("/userList")
@RequiresPermissions("user:view")//权限管理;
public String userInfo(){
return "userList";
}
//用户添加
@GetMapping("/userAdd")
@RequiresPermissions("user:add")//权限管理;
public String userInfoAdd(){
return "userAdd";
}
//用户删除
@GetMapping("/userDel")
@RequiresPermissions("user:del")//权限管理;
public String userDel(){
return "userDel";
}
}
9.数据库文件
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for hibernate_sequence
-- ----------------------------
DROP TABLE IF EXISTS `hibernate_sequence`;
CREATE TABLE `hibernate_sequence` (
`next_val` bigint(20) NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of hibernate_sequence
-- ----------------------------
INSERT INTO `hibernate_sequence` VALUES (1);
INSERT INTO `hibernate_sequence` VALUES (1);
INSERT INTO `hibernate_sequence` VALUES (1);
-- ----------------------------
-- Table structure for permission
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
`permissionId` int(11) NOT NULL,
`available` int(255) NULL DEFAULT NULL,
`permissionname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`parentid` int(11) NULL DEFAULT NULL,
`parentids` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`resourcetype` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`url` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
PRIMARY KEY (`permissionId`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of permission
-- ----------------------------
INSERT INTO `permission` VALUES (1, 1, '用户管理', 0, '0/', 'user:view', 'menu', 'user/userList');
INSERT INTO `permission` VALUES (2, 1, '用户添加', 1, '0/1', 'user:add', 'button', 'user/userAdd');
INSERT INTO `permission` VALUES (3, 1, '用户删除', 1, '0/1', 'user:del', 'button', 'user/userDel');
-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`roleid` int(11) NOT NULL,
`available` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`role` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`roleid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES (1, '1', '管理员', 'admin');
-- ----------------------------
-- Table structure for rolepermission
-- ----------------------------
DROP TABLE IF EXISTS `rolepermission`;
CREATE TABLE `rolepermission` (
`permissionid` int(11) NOT NULL,
`roleid` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`permissionid`) USING BTREE,
INDEX `FKoucecfqc8mdel2gdbo0e62mv`(`roleid`) USING BTREE,
CONSTRAINT `FKed6d8k3dnq28rvnoboj6y6dg3` FOREIGN KEY (`permissionid`) REFERENCES `permission` (`permissionId`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FKoucecfqc8mdel2gdbo0e62mv` FOREIGN KEY (`roleid`) REFERENCES `role` (`roleid`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of rolepermission
-- ----------------------------
INSERT INTO `rolepermission` VALUES (1, 1);
INSERT INTO `rolepermission` VALUES (3, 1);
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`userId` int(11) NOT NULL,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`salt` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`state` int(255) NULL DEFAULT NULL,
`createTime` datetime(0) NULL DEFAULT NULL,
`email` varchar(255) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL,
`expiredDate` date NULL DEFAULT NULL,
PRIMARY KEY (`userId`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'admin', '管理员', '6214e2068f13bd77460bbe7e8cdc8440', 'cmhit', 1, NULL, NULL, NULL);
-- ----------------------------
-- Table structure for userrole
-- ----------------------------
DROP TABLE IF EXISTS `userrole`;
CREATE TABLE `userrole` (
`roleid` int(11) NOT NULL,
`userId` int(11) NULL DEFAULT NULL,
PRIMARY KEY (`roleid`) USING BTREE,
INDEX `FK9e1tcga17su515dcucrlj3vtj`(`userId`) USING BTREE,
CONSTRAINT `FK63vxkaqx2q3q577qvuqhbtqs8` FOREIGN KEY (`roleid`) REFERENCES `role` (`roleid`) ON DELETE RESTRICT ON UPDATE RESTRICT,
CONSTRAINT `FK9e1tcga17su515dcucrlj3vtj` FOREIGN KEY (`userId`) REFERENCES `user` (`userId`) ON DELETE RESTRICT ON UPDATE RESTRICT
) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of userrole
-- ----------------------------
INSERT INTO `userrole` VALUES (1, 1);
SET FOREIGN_KEY_CHECKS = 1;
网友评论