随着业务的发展,传统的不分离前后端的Java项目逐渐减少,更多的时候是做到前后端分离,会话管理也就从传统的Session会话管理变为Jwt管理会话,本篇文章就是SpringBoot使用Jwt管理会话同时整合Security,完成权限操作。
提示:以下是本篇文章正文内容,下面案例可供参考,可以按照工程目录进行拷贝搭建,希望对同行有所帮助!
它是一个管理权限的框架,它包含了认证【即验证用户名密码】和授权【即用户可执行的操作】
代码如下:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE
Security_Jwt
Security_Jwt
1.0-SNAPSHOT
war
Security_Jwt Maven Webapp
http://www.example.com
UTF-8
1.8
1.8
4.12
1.2.17
1.14.8
1.1.16
2.6
2.1.3.RELEASE
2.7.0
3.0.1
1.2.10
5.1.39
org.springframework.boot
spring-boot-starter-web
org.springframework.security
spring-security-taglibs
org.springframework.boot
spring-boot-starter-security
org.thymeleaf.extras
thymeleaf-extras-springsecurity5
org.springframework.security
spring-security-jwt
io.jsonwebtoken
jjwt
0.9.0
org.projectlombok
lombok
${lombok.version}
io.springfox
springfox-swagger2
${springfox.version}
io.springfox
springfox-swagger-ui
${springfox.version}
com.github.pagehelper
pagehelper-spring-boot-starter
${pagehelper.spring.boot.starter.version}
com.baomidou
mybatis-plus-boot-starter
${mybatis.plus.boot.starter.version}
mysql
mysql-connector-java
${mysql-connector.version}
org.springframework.boot
spring-boot-starter-data-redis
${redis.version}
com.alibaba
fastjson
1.2.70
compile
apache-lang
commons-lang
2.0
Security_Jwt
maven-clean-plugin
3.1.0
maven-resources-plugin
3.0.2
maven-compiler-plugin
3.8.0
maven-surefire-plugin
2.22.1
maven-war-plugin
3.2.2
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
代码如下:
server:
port: 8080
#数据源
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_security_test?useUnicode=true&characterEncoding=UTF-8
username: root
password: root
#日期配置 yyyy-MM-dd HH:mm:ss
jackson:
date-format: yyyy-MM-dd HH:mm:ss
#映射xml
mybatis-plus:
mapper-locations: classpath:mapping/*.xml
type-aliases-package: com.dev.model
configuration:
#开启驼峰
map-underscore-to-camel-case: true
#分页插件
pagehelper:
auto-dialect: mysql
reasonable: true
support-methods-arguments: true
# JWT配置
jwt:
# 密匙Key
secret: limoumou
# HeaderKey
tokenHeader: Authorization
# Token前缀
tokenPrefix: Bearer
# 过期时间,单位秒
expiration: 86400
# 配置白名单(不需要认证)
antMatchers: /swagger-resources/**,/swagger-ui.html,/v2/api-docs,/webjars/**,/doc.html
代码如下:
package com.dev;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @return {@link }
* @throws
* @author 李庆伟
* @date 2021/7/14 14:41
*/
@SpringBootApplication
public class App8080 {
public static void main(String[] args) {
SpringApplication.run(App8080.class,args);
}
}
代码如下:
package com.dev.common;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.servlet.ServletResponse;
import java.io.PrintWriter;
import java.util.List;
/**
* @author 李庆伟
* @date 2020/4/16 9:52
*/
@Data
public class Result {
@ApiModelProperty(value = "返回码")
private int code;
@ApiModelProperty(value = "返回数据")
private Object data;
@ApiModelProperty(value = "返回描述")
private String msg;
@ApiModelProperty(value = "返回长度")
private long count;
/**返回成功 */
public static Result success(List
代码如下:
package com.dev.config.exception;
/**
* @author 李庆伟
* @date 2020/4/16 10:10
*/
public class MyException extends RuntimeException{
private int code;
private String msg;
public MyException(int code, String msg){
super(msg);
this.code = code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
代码如下:
package com.dev.config.exception;
import com.dev.common.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author 李庆伟
* @date 2020/4/16 10:11
*/
@ControllerAdvice
public class TopException {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Result handle(Exception e){
if(e instanceof MyException){
logger.error("业务日志",e);
MyException myException = (MyException) e;
return Result.error(myException.getCode(),myException.getMessage());
}else if(e instanceof AccessDeniedException){
return Result.error(403,"访问权限不足");
}
logger.error("系统日志",e);
return Result.error(1000,"业务繁忙");
}
}
代码如下:
package com.dev.config.security.handler;
import com.dev.common.Result;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 无权限处理类
* @author 李庆伟
* @date 2021/7/26 10:00
*/
@Component
public class UserAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
Result.responseJson(response, Result.response(403, "权限不足,拒绝访问", accessDeniedException.getMessage()));
}
}
代码如下:
package com.dev.config.security.handler;
import com.dev.config.security.Md5Util;
import com.dev.model.SysUserDetails;
import com.dev.service.impl.SysUserDetailsService;
import org.apache.commons.lang.StringUtils;
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.stereotype.Component;
/**
* @author 李庆伟
* @date 2021/7/26 10:49
*/
@Component
public class UserAuthenticationProvider implements AuthenticationProvider {
@Autowired
private SysUserDetailsService userDetailsService;
/**
* 身份验证
*/
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = (String) authentication.getPrincipal(); // 获取用户名
String password = (String) authentication.getCredentials(); // 获取密码
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
throw new UsernameNotFoundException("用户名或密码不能为空");
}
if(username.equals("admin") && password.equals("123456")){
SysUserDetails sysUserDetails = (SysUserDetails) userDetailsService.loadUserByUsername(username);
return new UsernamePasswordAuthenticationToken(sysUserDetails, password, sysUserDetails.getAuthorities());
} else if (username.equals("admin") && !password.equals("123456")){
throw new BadCredentialsException("用户名或密码错误");
} else {
SysUserDetails sysUserDetails = (SysUserDetails) userDetailsService.loadUserByUsername(username);
if (sysUserDetails == null) {
throw new UsernameNotFoundException("用户名不存在");
}
if(!sysUserDetails.getPassword().equals(Md5Util.MD5(password))){
throw new BadCredentialsException("用户名或密码错误");
}
return new UsernamePasswordAuthenticationToken(sysUserDetails, password, sysUserDetails.getAuthorities());
}
}
/**
* 支持指定的身份验证
*/
@Override
public boolean supports(Class> authentication) {
return true;
}
}
代码如下:
package com.dev.config.security.handler;
import com.dev.common.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 登录失败处理类
* @author 李庆伟
* @date 2021/7/26 10:03
*/
@Component
public class UserLoginFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) {
Result.responseJson(response, Result.response(500, "登录失败", exception.getMessage()));
}
}
代码如下:
package com.dev.config.security.handler;
import com.dev.common.Result;
import com.dev.config.security.JWTTokenUtil;
import com.dev.model.SysUserDetails;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* 登录成功处理类
* @author 李庆伟
* @date 2021/7/26 10:02
*/
@Component
public class UserLoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
SysUserDetails sysUserDetails = (SysUserDetails) authentication.getPrincipal();
String token = JWTTokenUtil.createAccessToken(sysUserDetails);
Map tokenMap = new HashMap<>();
tokenMap.put("token", token);
Result.responseJson(response, Result.response(0, "登录成功", tokenMap));
}
}
代码如下:
package com.dev.config.security.handler;
import com.dev.common.Result;
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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 登出成功处理类
* @author 李庆伟
* @date 2021/7/26 10:04
*/
@Component
public class UserLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) {
SecurityContextHolder.clearContext();
Result.responseJson(response, Result.response(200, "登出成功", null));
}
}
代码如下:
package com.dev.config.security.handler;
import com.dev.common.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 李庆伟
* @date 2021/7/27 15:39
*/
@Component
public class UserNotLoginHandler implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
Result.responseJson(response, Result.response(401, "未登录", authException.getMessage()));
}
}
代码如下:
package com.dev.config.security.handler;
import com.dev.config.exception.MyException;
import com.dev.model.SysUserDetails;
import com.dev.model.TSysRes;
import com.dev.service.TSysResService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author 李庆伟
* @date 2021/7/26 14:33
*/
@Configuration
@Component
public class UserPermissionEvaluator implements PermissionEvaluator {
@Autowired
private TSysResService tSysResService;
/**
* 判断是否拥有权限
* [authentication, targetUrl, permission]
* @return {@link boolean}
* @throws
* @author 李庆伟
* @date 2021/12/7 19:42
*/
@Override
public boolean hasPermission(Authentication authentication, Object targetUrl, Object permission) {
SysUserDetails sysUserDetails = null;
try {
sysUserDetails = (SysUserDetails) authentication.getPrincipal();
} catch (Exception e){
throw new MyException(403,"权限不足");
}
Set permissions = new HashSet(); // 用户权限
List authList = tSysResService.findResByUserId(sysUserDetails.getId());
for (int i = 0; i < authList.size() ; i++) {
permissions.add(authList.get(i).getPermission());
}
// 判断是否拥有权限
if (permissions.contains(permission.toString())) {
return true;
}
return false;
}
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
Object permission) {
return false;
}
}
代码如下:
package com.dev.config.security;
import com.dev.config.security.handler.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
/**
* @author 李庆伟
* @date 2021/7/26 14:36
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法权限注解
public class AutoSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 无权限处理类
*/
@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;
/**
* 加密方式,没使用这种加密方式
*/
@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);
}
@Value("${jwt.antMatchers}")
private String antMatchers;//白名单,这里是不做验证的方法
/**
* 安全权限配置
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() // 权限配置
.antMatchers(antMatchers.split(",")).permitAll()// 获取白名单(不进行权限验证)
.anyRequest().authenticated() // 其他的需要登陆后才能访问
.and().httpBasic().authenticationEntryPoint(userNotLoginHandler) // 配置未登录处理类
.and().formLogin().loginProcessingUrl("/user/login")// 配置登录URL
//.and().formLogin().loginPage("/user/login")// 配置登录URL
.successHandler(userLoginSuccessHandler) // 配置登录成功处理类
.failureHandler(userLoginFailureHandler) // 配置登录失败处理类
.and().logout().logoutUrl("/logout/submit")// 配置登出地址
.logoutSuccessHandler(userLogoutSuccessHandler) // 配置用户登出处理类
.and().logout() //退出登录相关配置
.logoutSuccessUrl("/page/index") //退出成功后跳转的页面
.deleteCookies("JSESSIONID") //退出时要删除的Cookies的名字
.and().exceptionHandling().accessDeniedHandler(userAccessDeniedHandler)// 配置没有权限处理类
.and().cors()// 开启跨域
.and().csrf().disable(); // 禁用跨站请求伪造防护
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 禁用session(使用Token认证)
http.headers().cacheControl(); // 禁用缓存
http.addFilter(new JWTAuthenticationFilter(authenticationManager())); 添加JWT过滤器
}
}
代码如下:
package com.dev.config.security;
import com.dev.model.SysUserDetails;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 李庆伟
* @date 2021/7/26 10:52
*/
public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
// 取出Token
String token = request.getHeader(JWTConfig.tokenHeader);
if (token != null && token.startsWith(JWTConfig.tokenPrefix)) {
SysUserDetails sysUserDetails = JWTTokenUtil.parseAccessToken(token);
if (sysUserDetails != null) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
sysUserDetails, sysUserDetails.getId(), sysUserDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(request, response);
}
}
代码如下:
package com.dev.config.security;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @author 李庆伟
* @date 2021/7/26 9:54
*/
@Component
@ConfigurationProperties(prefix = "jwt")
public class JWTConfig {
/**
* 密匙Key
*/
public static String secret;
/**
* HeaderKey
*/
public static String tokenHeader;
/**
* Token前缀
*/
public static String tokenPrefix;
/**
* 过期时间
*/
public static Integer expiration;
/**
* 配置白名单
*/
public static String antMatchers;
/**
* 将过期时间单位换算成毫秒
*
* @param expiration 过期时间,单位秒
*/
public void setExpiration(Integer expiration) {
this.expiration = expiration * 1000;
}
public void setSecret(String secret) {
this.secret = secret;
}
public void setTokenHeader(String tokenHeader) {
this.tokenHeader = tokenHeader;
}
public void setTokenPrefix(String tokenPrefix) {
this.tokenPrefix = tokenPrefix + " ";
}
public void setAntMatchers(String antMatchers) {
this.antMatchers = antMatchers;
}
}
代码如下:
package com.dev.config.security;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.dev.model.SysUserDetails;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.*;
/**
* @author 李庆伟
* @date 2021/7/26 9:57
*/
@Slf4j
public class JWTTokenUtil {
/**
* 创建Token
*
* @param sysUserDetails 用户信息
* @return
*/
public static String createAccessToken(SysUserDetails sysUserDetails) {
String token = Jwts.builder().setId(// 设置JWT
sysUserDetails.getId()) // 用户Id
.setSubject(sysUserDetails.getUsername()) // 主题
.setIssuedAt(new Date()) // 签发时间
.setIssuer("limoumou") // 签发者
.setExpiration(new Date(System.currentTimeMillis() + JWTConfig.expiration)) // 过期时间
.signWith(SignatureAlgorithm.HS512, JWTConfig.secret) // 签名算法、密钥
.claim("authorities", JSON.toJSONString(sysUserDetails.getAuthorities())).compact(); // 自定义其他属性,如用户组织机构ID,用户所拥有的角色,用户权限信息等
return JWTConfig.tokenPrefix + token;
}
/**
* 解析Token
*
* @param token Token信息
* @return
*/
public static SysUserDetails parseAccessToken(String token) {
SysUserDetails sysUserDetails = null;
if (StringUtils.isNotEmpty(token)) {
try {
// 去除JWT前缀
token = token.substring(JWTConfig.tokenPrefix.length());
// 解析Token
Claims claims = Jwts.parser().setSigningKey(JWTConfig.secret).parseClaimsJws(token).getBody();
// 获取用户信息
sysUserDetails = new SysUserDetails();
sysUserDetails.setId(claims.getId());
sysUserDetails.setUsername(claims.getSubject());
// 获取角色
Set authorities = new HashSet();
String authority = claims.get("authorities").toString();
if (StringUtils.isNotEmpty(authority)) {
List
代码如下:
package com.dev.config.security;
import java.security.MessageDigest;
/**
* @author 李庆伟
* @date 2021/7/28 15:54
*/
public class Md5Util {
public final static String MD5(String s) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
try {
// 密码+盐组合
byte[] btInput = s.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 测试
* [args]
* @throws
* @author 李庆伟
* @date 2021/12/13 19:38
*/
public static void main(String[] args) {
String pwd = Md5Util.MD5("123456");
System.out.println(pwd );
}
}
代码如下:
package com.dev.config;
import com.dev.App8080;
import com.fasterxml.classmate.TypeResolver;
import com.google.common.collect.Sets;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.OperationBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiDescription;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.ApiListingScannerPlugin;
import springfox.documentation.spi.service.contexts.DocumentationContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.spring.web.readers.operation.CachingOperationNameGenerator;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 接口文档配置
* @return {@link }
* @throws
* @author 李庆伟
* @date 2021/7/19 17:15
*/
@ConditionalOnWebApplication
@Configuration
@EnableSwagger2
public class SwaggerConfig implements ApiListingScannerPlugin {
/**
* Swagger2的配置文件,这里可以配置Swagger2的一些基本的内容,比如扫描的包等等
* []
* @return {@link Docket}
* @throws
* @author 李庆伟
* @date 2021/12/13 16:28
*/
@Bean
public Docket createRestApi() {
List pars = new ArrayList<>();
ParameterBuilder token = new ParameterBuilder();
token.name("Authorization").description("Authorization")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false).build();
pars.add(token.build());
ParameterBuilder languageCode = new ParameterBuilder();
languageCode.name("languageCode").description("languageCode")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false).build();
pars.add(languageCode.build());
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage(App8080.class.getPackage().getName()))
.build()
.globalOperationParameters(pars)
.apiInfo(apiInfo());
}
/**
* 构建API文档的详细信息函数
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("项目接口 API")
.version("1.0")
.build();
}
/**
* Security指定的登录接口不会出现在swagger中,为了方便可以自定义登录接口在swagger中。
* [documentationContext]
* @return {@link List}
* @throws
* @author 李庆伟
* @date 2021/12/13 16:20
*/
@Override
public List apply(DocumentationContext documentationContext) {
return new ArrayList(
Arrays.asList(
new ApiDescription(
"/user/login", //url
"登录", //描述
Arrays.asList(
new OperationBuilder(
new CachingOperationNameGenerator())
.method(HttpMethod.POST)//http请求类型
.produces(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE))
.summary("登录")
.notes("登录")//方法描述
.tags(Sets.newHashSet("登录"))//归类标签
.parameters(
Arrays.asList(
new ParameterBuilder()
.description("用户名")
.type(new TypeResolver().resolve(String.class))
.name("username")
.parameterType("query")
.parameterAccess("access")
.required(true)
.modelRef(new ModelRef("string")) //<5>
.build(),
new ParameterBuilder()
.description("密码")
.type(new TypeResolver().resolve(String.class))
.name("password")
.parameterType("query")
.parameterAccess("access")
.required(true)
.modelRef(new ModelRef("string")) //<5>
.build()
))
.build()),
false)));
}
@Override
public boolean supports(DocumentationType documentationType) {
return DocumentationType.SWAGGER_2.equals(documentationType);
}
}
代码如下:
package com.dev.controller;
import com.dev.common.Result;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
/**
* 系统用户服务
* @author 李庆伟
* @date 2021/7/19 17:04
*/
@Slf4j
@RequestMapping("tSysUser")
@RestController
@Api(value = "系统用户服务", tags = "系统用户服务")
public class TSysUserController {
@PreAuthorize("hasRole('ROLE_/tSysUser/findByPage')")
@PostMapping("findByPage")
@ApiOperation(value = "添加系统用户", notes = "添加系统用户", produces = "application/json")
public Result findByPage(){
log.info("测试用户分页查询权限");
return Result.success("测试用户分页查询权限");
}
@PreAuthorize("hasRole('ROLE_/tSysUser/add')")
@PostMapping("add")
@ApiOperation(value = "添加系统用户", notes = "添加系统用户", produces = "application/json")
public Result add(){
log.info("测试用户添加权限");
return Result.success("测试用户添加权限");
}
@PreAuthorize("hasRole('ROLE_/tSysUser/edit')")
@PostMapping("edit")
@ApiOperation(value = "修改系统用户", notes = "修改系统用户", produces = "application/json")
public Result edit(){
log.info("测试用户编辑权限");
return Result.success("测试用户编辑权限");
}
@PreAuthorize("hasRole('ROLE_/tSysUser/delete')")
@PostMapping("delete")
@ApiOperation(value = "删除系统用户", notes = "删除系统用户", produces = "application/json")
public Result delete(){
log.info("测试用户删除权限");
return Result.success("测试用户删除权限");
}
}
代码如下:
package com.dev.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dev.model.TSysRes;
import org.apache.ibatis.annotations.Mapper;
/**
* @author 李庆伟
* @date 2021/7/19 17:06
*/
@Mapper
public interface TSysResMapper extends BaseMapper {
}
代码如下:
package com.dev.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dev.model.TSysRole;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author 李庆伟
* @date 2021/7/19 17:06
*/
@Mapper
public interface TSysRoleMapper extends BaseMapper {
/**
* 根据用户名查询用户有的角色
* [userId]
* @return {@link List}
* @throws
* @author 李庆伟
* @date 2021/7/27 14:40
*/
@Select("SELECT r.* FROM t_sys_role r " +
"LEFT JOIN t_sys_user_role ur ON ur.role_id = r.id " +
"WHERE " +
"ur.user_id = #{userId} ")
List findRoleByUserId(String userId);
}
代码如下:
package com.dev.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dev.model.TSysRoleRes;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
/**
* @author 李庆伟
* @date 2021/7/19 17:06
*/
@Mapper
public interface TSysRoleResMapper extends BaseMapper {
List selectRoleResByMap(Map map);
}
代码如下:
package com.dev.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dev.model.TSysUser;
import org.apache.ibatis.annotations.Mapper;
/**
* @author 李庆伟
* @date 2021/7/19 17:06
*/
@Mapper
public interface TSysUserMapper extends BaseMapper {
}
代码如下:
package com.dev.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dev.model.TSysUserRole;
import org.apache.ibatis.annotations.Mapper;
/**
* @author 李庆伟
* @date 2021/7/19 17:06
*/
@Mapper
public interface TSysUserRoleMapper extends BaseMapper {
}
代码如下:
package com.dev.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.io.Serializable;
import java.util.Collection;
/**
* @author 李庆伟
* @date 2021/7/26 9:48
*/
@Data
@EqualsAndHashCode(callSuper = false)
public class SysUserDetails extends TSysUser implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户角色
*/
private Collection 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;
}
}
代码如下:
package com.dev.model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 系统资源实体
* @return {@link }
* @throws
* @author 李庆伟
* @date 2021/7/22 9:25
*/
@Data
@TableName("t_sys_res")
public class TSysRes {
@TableId
private String id;//主键
private String name;//资源名称
private String resUrl;//资源路径
private String permission;//做拦截的code
private String resType;//0菜单 1按钮
private String pid;//父级id
private String icon;//菜单图标
private String createUser;//创建人
private Date createDate;//创建时间
}
代码如下:
package com.dev.model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 系统角色实体
* @author 李庆伟
* @date 2021/7/19 17:00
*/
@Data
@TableName("t_sys_role")
public class TSysRole {
@TableId
private String id;//主键
private String roleName;//角色名称
private String roleExplain;//角色描述
private String createUser;//创建人
private Date createDate;//创建时间
}
代码如下:
package com.dev.model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 系统角色资源实体
* @author 李庆伟
* @date 2021/7/19 17:00
*/
@Data
@TableName("t_sys_role_res")
public class TSysRoleRes {
@TableId
private String id;//主键
private String roleId;//角色id
private String resId;//资源id
}
代码如下:
package com.dev.model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 系统用户实体
* @author 李庆伟
* @date 2021/7/19 17:00
*/
@Data
@TableName("t_sys_user")
public class TSysUser implements Serializable {
private static final long serialVersionUID = 1L;
@TableId
private String id;//主键
private String username;//用户名
private String password;//密码
private String nickName;//昵称
private String cellPhone;//电话
private String mail;//邮件
private Date birthday;//生日
private String status;//状态(0-正常,1-禁用,2-删除)
private String accountType;//1系统账号 2客户账号
private String inviteCode;//邀请码
private String sex;//性别:0男 1女
private String address;//地址
private Integer upNum;//获赞总量
private Integer readNum;//文章被阅读总量
private String sign;//签名
private String pictureId;//用户头像
private String createUser;//创建人
private Date createDate;//创建时间
}
代码如下:
package com.dev.model;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 系统用户角色实体
* @author 李庆伟
* @date 2021/7/19 17:00
*/
@Data
@TableName("t_sys_user_role")
public class TSysUserRole {
@TableId
private String id;//主键
private String userId;//用户名id
private String roleId;//角色id
}
代码如下:
package com.dev.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dev.model.SysUserDetails;
import com.dev.model.TSysRes;
import com.dev.model.TSysUser;
import com.dev.dao.TSysResMapper;
import com.dev.service.TSysResService;
import com.dev.service.TSysUserService;
import com.github.pagehelper.util.StringUtil;
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.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @author 李庆伟
* @date 2021/7/26 10:44
*/
@Service
public class SysUserDetailsService implements UserDetailsService {
@Autowired
private TSysUserService tSysUserService;
@Resource
private TSysResMapper tSysResMapper;
@Autowired
private TSysResService tSysResService;
/**
* 说明:重写UserDetailsService中的loadUserByUsername,就是查询用户详细信息封装到 UserDetails
* 业务:
* ①如果是admin会拥有全部权限
* ②如果不是admin就去查用户信息和用户拥有的权限
* [username]
* @return {@link UserDetails}
* @throws
* @author 李庆伟
* @date 2021/12/7 19:49
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List resList = null;
if(username.equals("admin")){
TSysUser tSysUser = new TSysUser();
tSysUser.setId("admin");
tSysUser.setUsername("admin");
tSysUser.setNickName("系统管理员");
SysUserDetails sysUserDetails = new SysUserDetails();
BeanUtils.copyProperties(tSysUser, sysUserDetails);
Set authorities = new HashSet<>(); // 角色集合
//admin用户有的资源集合
resList = tSysResMapper.selectList(new QueryWrapper<>());
for (int i = 0; i < resList.size() ; i++) {
if(StringUtil.isNotEmpty(resList.get(i).getPermission())){
authorities.add(new SimpleGrantedAuthority("ROLE_" + resList.get(i).getPermission()));
}
}
sysUserDetails.setAuthorities(authorities);
return sysUserDetails;
}
TSysUser tSysUser = tSysUserService.findByUsername(username);
if (tSysUser != null) {
SysUserDetails sysUserDetails = new SysUserDetails();
BeanUtils.copyProperties(tSysUser, sysUserDetails);
Set authorities = new HashSet<>(); // 角色集合
resList = tSysResService.findResByUserId(sysUserDetails.getId());//当前用户有的资源集合
if(resList != null){
for (int i = 0; i < resList.size() ; i++) {
if(StringUtil.isNotEmpty(resList.get(i).getPermission())){
authorities.add(new SimpleGrantedAuthority("ROLE_" + resList.get(i).getPermission()));
}
}
}
sysUserDetails.setAuthorities(authorities);
return sysUserDetails;
}
return null;
}
}
代码如下:
package com.dev.service.impl;
import com.dev.model.TSysRes;
import com.dev.model.TSysRole;
import com.dev.dao.TSysResMapper;
import com.dev.dao.TSysRoleMapper;
import com.dev.dao.TSysRoleResMapper;
import com.dev.service.TSysResService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 系统角色服务
* @author 李庆伟
* @date 2021/7/19 17:06
*/
@Service
public class TSysResServiceImpl implements TSysResService {
@Resource
private TSysResMapper tSysResMapper;
@Resource
private TSysRoleMapper tSysRoleMapper;
@Resource
private TSysRoleResMapper tSysRoleResMapper;
/**
* 根据用户id查询用户拥有的资源
* [userId]
* @return {@link List< TSysRes>}
* @throws
* @author 李庆伟
* @date 2021/12/7 20:34
*/
@Override
public List findResByUserId(String userId) {
//获取用户有的角色
//根据当前登录用户获取角色
List roleList = tSysRoleMapper.findRoleByUserId(userId);
if(roleList == null || roleList.size() == 0){ //如果用户没有角色返回没有权限
return null;
}
//根据角色获取菜单资源id关系集合
Map map = new HashMap<>();
map.put("roleList",roleList);
List tSysRoleResList = tSysRoleResMapper.selectRoleResByMap(map);
if(tSysRoleResList == null || tSysRoleResList.size() == 0){ //如果用户没有角色返回没有权限
return null;
}
//根据资源id获取菜单资源
return tSysResMapper.selectBatchIds(tSysRoleResList);
}
}
代码如下:
package com.dev.service.impl;
import com.dev.service.TSysRoleResService;
import org.springframework.stereotype.Service;
/**
* 系统角色资源服务
* @author 李庆伟
* @date 2021/7/19 17:06
*/
@Service
public class TSysRoleResServiceImpl implements TSysRoleResService {
}
代码如下:
package com.dev.service.impl;
import com.dev.service.TSysRoleService;
import org.springframework.stereotype.Service;
/**
* 系统角色服务
* @author 李庆伟
* @date 2021/7/19 17:06
*/
@Service
public class TSysRoleServiceImpl implements TSysRoleService {
}
代码如下:
package com.dev.service.impl;
import com.dev.service.TSysUserRoleService;
import org.springframework.stereotype.Service;
/**
* 系统用户角色服务
* @author 李庆伟
* @date 2021/7/19 17:06
*/
@Service
public class TSysUserRoleServiceImpl implements TSysUserRoleService {
}
代码如下:
package com.dev.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dev.model.TSysUser;
import com.dev.dao.TSysUserMapper;
import com.dev.service.TSysUserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 系统用户服务
* @author 李庆伟
* @date 2021/7/19 17:06
*/
@Service
public class TSysUserServiceImpl implements TSysUserService {
@Resource
private TSysUserMapper tSysUserMapper;
/**
* 根据用户名查询用户
* [username]
* @return {@link TSysUser}
* @throws
* @author 李庆伟
* @date 2021/7/27 11:11
*/
public TSysUser findByUsername(String username) {
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("username",username);
return tSysUserMapper.selectOne(queryWrapper);
}
}
代码如下:
package com.dev.service;
import com.dev.model.TSysRes;
import java.util.List;
/**
* @author 李庆伟
* @date 2021/7/19 17:05
*/
public interface TSysResService {
List findResByUserId(String userId);
}
代码如下:
package com.dev.service;
/**
* @author 李庆伟
* @date 2021/7/19 17:05
*/
public interface TSysRoleResService {
}
代码如下:
package com.dev.service;
/**
* @author 李庆伟
* @date 2021/7/19 17:05
*/
public interface TSysRoleService {
}
代码如下:
package com.dev.service;
/**
* @author 李庆伟
* @date 2021/7/19 17:05
*/
public interface TSysUserRoleService {
}
代码如下:
package com.dev.service;
import com.dev.model.TSysUser;
/**
* @author 李庆伟
* @date 2021/7/19 17:05
*/
public interface TSysUserService {
TSysUser findByUsername(String username);
}
导入数据库sql
/*
Navicat Premium Data Transfer
Source Server : 本机数据库mysql
Source Server Type : MySQL
Source Server Version : 50143
Source Host : localhost:3306
Source Schema : my_security_test
Target Server Type : MySQL
Target Server Version : 50143
File Encoding : 65001
Date: 08/12/2021 21:17:27
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_sys_res
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_res`;
CREATE TABLE `t_sys_res` (
`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源id',
`name` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源名称',
`res_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '资源路径',
`permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '资源code',
`res_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '0菜单 1按钮',
`pid` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '父级id',
`create_user` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`create_date` datetime DEFAULT NULL,
`icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '菜单图标'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-资源表【菜单】' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_sys_res
-- ----------------------------
INSERT INTO `t_sys_res` VALUES ('101', '用户添加', '/tSysUser/add', '/tSysUser/add', '1', '100', NULL, NULL, '');
INSERT INTO `t_sys_res` VALUES ('100', '用户管理', '/tSysUser/findByPage', '/tSysUser/findByPage', '0', '', NULL, NULL, 'fa fa-snowflake-o');
INSERT INTO `t_sys_res` VALUES ('102', '用户修改', '/tSysUser/edit', '/tSysUser/edit', '1', '100', NULL, NULL, 'fa fa-home');
INSERT INTO `t_sys_res` VALUES ('103', '用户删除', '/tSysUser/delete', '/tSysUser/delete', '1', '100', NULL, NULL, 'fa fa-home');
-- ----------------------------
-- Table structure for t_sys_role
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_role`;
CREATE TABLE `t_sys_role` (
`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id',
`role_name` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色名称',
`role_explain` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '描述',
`create_user` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '创建人',
`create_date` datetime DEFAULT NULL COMMENT '创建时间'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-角色表' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_sys_role
-- ----------------------------
INSERT INTO `t_sys_role` VALUES ('277144172094291968', '部门经理', '部门经理', NULL, '2021-08-27 10:22:51');
INSERT INTO `t_sys_role` VALUES ('277144675716956160', '普通员工', '普通员工', NULL, '2021-08-27 10:24:51');
INSERT INTO `t_sys_role` VALUES ('277646459757658112', '测试员工', '测试员工', '', '2021-08-28 19:38:46');
-- ----------------------------
-- Table structure for t_sys_role_res
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_role_res`;
CREATE TABLE `t_sys_role_res` (
`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
`role_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id',
`res_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源id'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-角色资源表中间表' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_sys_role_res
-- ----------------------------
INSERT INTO `t_sys_role_res` VALUES ('1234', '277144675716956160', '101');
INSERT INTO `t_sys_role_res` VALUES ('12345', '277144675716956160', '100');
INSERT INTO `t_sys_role_res` VALUES ('123456', '277144172094291968', '100');
INSERT INTO `t_sys_role_res` VALUES ('123457', '277144172094291968', '101');
INSERT INTO `t_sys_role_res` VALUES ('123458', '277144172094291968', '102');
-- ----------------------------
-- Table structure for t_sys_user
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_user`;
CREATE TABLE `t_sys_user` (
`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
`username` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码',
`nick_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '昵称',
`cell_phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '手机号',
`mail` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '邮件',
`birthday` datetime DEFAULT NULL COMMENT '生日',
`status` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '状态(0-正常,1-删除,2-禁用)',
`account_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '1系统账号 2客户账号',
`invite_code` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '邀请码',
`sex` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '性别:0男 1女',
`up_num` int(11) DEFAULT NULL COMMENT '所有获赞总量',
`read_num` int(11) DEFAULT NULL COMMENT '所有文章阅读总量',
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '地址',
`create_user` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '创建人',
`create_date` datetime DEFAULT NULL COMMENT '创建时间',
`sign` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用户签名',
`picture_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用户头像'
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-用户表' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_sys_user
-- ----------------------------
INSERT INTO `t_sys_user` VALUES ('276866508766838784', 'liqingwei', 'E10ADC3949BA59ABBE56E057F20F883E', '李庆伟', '15801174628', '[email protected]', NULL, '0', '1', '3781941dd39446b89e98cb661766aade', NULL, 0, 0, NULL, NULL, '2021-08-26 15:59:31', NULL, NULL);
INSERT INTO `t_sys_user` VALUES ('277657251341139964', 'zhangsan', 'E10ADC3949BA59ABBE56E057F20F883E', '张三', '15801174626', '[email protected]', '2021-08-04 00:00:00', '0', '1', 'ea819ca462914e938943752d48ae8bcc', '0', 0, 0, '河南北京北', 'admin', '2021-08-28 20:21:38', '啥也不是。。。', '287348042074423296');
-- ----------------------------
-- Table structure for t_sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `t_sys_user_role`;
CREATE TABLE `t_sys_user_role` (
`id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
`user_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户id',
`role_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-用户角色中间表' ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_sys_user_role
-- ----------------------------
INSERT INTO `t_sys_user_role` VALUES ('111', '276866508766838784', '277144675716956160');
INSERT INTO `t_sys_user_role` VALUES ('222', '277657251341139964', '277144172094291968');
SET FOREIGN_KEY_CHECKS = 1;
访问地址:http://localhost:8080/swagger-ui.html
一点点。。。。。。。。。。。