失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > springsecurity整合jwt实现授权认证 权限分配

springsecurity整合jwt实现授权认证 权限分配

时间:2021-01-22 11:39:59

相关推荐

springsecurity整合jwt实现授权认证 权限分配

1.前期准备工作

1.1首先需要导入jwt依赖和springsecurity的依赖

<!--security 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!--JWT 依赖 用来做登录验证--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.0</version></dependency>

1.2自定义application.yml配置jwt属性

# jwt令牌jwt:# JWT存储的请求头# 正常前端请求 tokenHeader:Authorization 是key tokenHead:Bearer是它的 value 加上空格然后jwt令牌,组成一个请求tokenHeader: Authorization# JWT 加解密使用的密钥secret: yeb-secret# JWT的超期限时间(60*60*24)expiration: 604800# JWT 负载中拿到开头tokenHead: Bearer

1.3编写jwt工具类

import io.jsonwebtoken.Claims;import io.jsonwebtoken.ExpiredJwtException;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import org.springframework.beans.factory.annotation.Value;import org.springframework.security.core.userdetails.UserDetails;import org.ponent;import java.util.Date;import java.util.HashMap;import java.util.Map;/*** jwt token 工具类*/@Component@SuppressWarnings("all")public class JwtTokenUtils {//用户名的keyprivate static final String CLAIM_KEY_USERNAME="sub";//jwt创建时间private static final String CLAIM_KEY_CREATED="created";@Value("${jwt.secret}")//jwt 密钥private String secret;@Value("${jwt.expiration}")//失效时间private Long expiration;/*** 根据用户信息生成token* @param userDetails* @return*///用户信息通过Security中的 UserDetails 拿取public String generateToken(UserDetails userDetails){Map<String,Object> jwtToken = new HashMap<>();jwtToken.put(CLAIM_KEY_USERNAME,userDetails.getUsername());jwtToken.put(CLAIM_KEY_CREATED,new Date());//根据荷载生成jwtreturn generateToken(jwtToken);}/*** 从token中获取登录用户名* @param token* @return*/public String getUserNameFromToken(String token){String username;try {Claims claims = getClaimsFromToken(token);//通过荷载 claims 就可以拿到用户名username = claims.getSubject();} catch (Exception e) {username = null;}return username;}/*** 判断token是否有效* @param token* @param userDetails* @return*/public boolean validateToken(String token, UserDetails userDetails) {String username = getUserNameFromToken(token);return username.equals(userDetails.getUsername()) && !isTokenExpired(token);}/*** 判断token是否可以被刷新* 如果过期了就可以被刷新,如果没过期就不能被刷新* @param token* @return*/public boolean canRefresh(String token){return !isTokenExpired(token);}/*** 刷新token* @param token* @return*/public String refreshToken(String token){Claims claims = getClaimsFromToken(token);//将创建时间改成当前时间,就相当于去刷新了claims.put(CLAIM_KEY_CREATED,new Date());return generateToken(claims);}/*** 判断token是否失效* @param token* @return*/private boolean isTokenExpired(String token) {Date expireDate = getExpiredDateFromToken(token);//判断token时间是否是当前时间的前面 .beforereturn expireDate.before(new Date());}/*** 从token中获取过期时间* @param token* @return*/private Date getExpiredDateFromToken(String token) {//从token里面获取荷载//因为token的过期时间有对应的数据,设置过的,荷载里面就有设置过的数据Claims claims = getClaimsFromToken(token);return claims.getExpiration();}/*** 从token中获取荷载* @param token* @return*/private Claims getClaimsFromToken(String token) {//拿到荷载Claims claims = null ;try {claims = Jwts.parser()//签名.setSigningKey(secret)//密钥.parseClaimsJws(token).getBody();} catch (ExpiredJwtException e) {e.printStackTrace();}return claims;}/*** 根据荷载生成 JWT TOKEN* @param claims* @return*/private String generateToken(Map<String,Object> claims){return Jwts.builder().setClaims(claims)//失效时间.setExpiration(generateExpirationDate())//签名.signWith(SignatureAlgorithm.HS512, secret).compact();}/*** 生成token失效时间* @return*/private Date generateExpirationDate() {return new Date(System.currentTimeMillis() + expiration * 1000);}}

1.4登录流程

1.5security登录流程

UsernamePasswordAuthenticationFilter:是我们最常用的用户名和密码认证方式的主要处理类,构造了一个UsernamePasswordAuthenticationToken对象实现类,将用请求信息封authentication

Authentication接口: 封装了用户相关信息

AuthenticationManage:定义了认证Authentication的方法,是认证相关的核心接口,也是发起认证的出发点,因为在实际需求中,我们可能会允许用户使用用户名+密码登录,同时允许用户使用邮箱+密码,手机号码+密码登录,甚至,可能允许用户使用指纹登录(还有这样的操作?没想到吧),所以说AuthenticationManager一般不直接认证,AuthenticationManager接口的常用实现类ProviderManager 内部会维护一个List列表,存放多种认证方式,实际上这是委托者模式的应用(Delegate)。也就是说,核心的认证入口始终只有一个:AuthenticationManager

AuthenticationManager,ProviderManager ,AuthenticationProvider…

用户名+密码(UsernamePasswordAuthenticationToken),邮箱+密码,手机号码+密码登录则对应了三个AuthenticationProvider

DaoAuthenticationProvider:用于解析并认证 UsernamePasswordAuthenticationToken 的这样一个认证服务提供者,对应以上的几种登录方式。

UserDetailsService接口:Spring Security 会将前端填写的username 传给 UserDetailService.loadByUserName方法。我们只需要从数据库中根据用户名查找到用户信息然后封装为UserDetails的实现类返回给SpringSecurity 即可,自己不需要进行密码的比对工作,密码比对交由SpringSecurity处理。

UserDetails接口:提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回。然后将这些信息封装到Authentication对象中。

1.6 security基本原理

2.登录流程

继承UserDetails

@Data@EqualsAndHashCode(callSuper = false)@Accessors(chain = true)@TableName("f_user")@ApiModel(value="FUser对象")public class FUser implements Serializable, UserDetails{private static final long serialVersionUID = 1L;@TableId(type = IdType.ASSIGN_UUID)@ApiModelProperty(value = "用户唯一标识")private String id;@ApiModelProperty(value = "用户名")private String username;@ApiModelProperty(value = "手机号")private String phone;@ApiModelProperty(value = "密码")private String password;//自定义解析器@JsonDeserialize(using = CustomAuthorityDeserializer.class)@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {List<SimpleGrantedAuthority> authorities = roles.stream()//将获得的权限名字通过 SimpleGrantedAuthority 转换成授权的 url.map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList());return authorities;}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;}@TableField(exist = false)private List<FRole> roles;}

UserController

@Api("用户接口")@RestController@RequestMapping("/user")public class FUserController {@Autowiredprivate AccountUtil accountUtil;@Autowiredprivate IFUserService userService;@ApiOperation("是否注册")@RequestMapping(value ="/exist",method = RequestMethod.POST)public RespBean existUser(@RequestBody FUser fUser){String desEncrypt = accountUtil.desEncrypt(fUser.getPhone());FUser user = userService.getOne(new QueryWrapper<FUser>().eq("phone", desEncrypt));if(ObjectUtil.isEmpty(user)){return RespBean.success("可以注册,手机号还未注册");}return RespBean.error("手机号已注册");}@ApiOperation("注册")@RequestMapping(value ="/register",method = RequestMethod.PUT)public RespBean registerUser(@RequestBody FUser user){user.setPhone(accountUtil.desEncrypt(user.getPhone()));boolean save = userService.save(user);if(save){return RespBean.success("注册成功!");}return RespBean.error("注册失败");}@ApiOperation("登录之后返回token")@RequestMapping(value ="/login",method = RequestMethod.POST)public RespBean loginUser(@RequestBody LoginUser loginUser, HttpServletRequest request){return userService.loginUser(loginUser.getPhone(),loginUser.getPassword(),request);}@ApiOperation(value = "获取当前登录用户的信息")@GetMapping("/info")public FUser getUserInfo(Principal principal){if (principal == null){return null;}String username = principal.getName();FUser user = userService.getOneUser(username);user.setPassword(null);user.setRoles(userService.getRoles(user.getId()));return user;}}

服务实现类,这里我采用手机号登录,可以根据手机号查出这个对象不为空的话再去获得其

username再放给loadbyusername

@Servicepublic class FUserServiceImpl extends ServiceImpl<FUserMapper, FUser> implements IFUserService {@Autowiredprivate FRoleMapper roleMapper;@Autowiredprivate JwtTokenUtils jwtTokenUtils;@Autowiredprivate IFUserService userService;@Autowiredprivate UserDetailsService userDetailsService;//密码加密@Autowiredprivate PasswordEncoder bCryptPasswordEncoder;//将配置文件中存的值取过来@Value("${jwt.tokenHead}")private String tokenHead;@Overridepublic RespBean loginUser(String phone, String password, HttpServletRequest request) {//查询数据库中是否存在用户并判断当前登录用户密码与数据库密码是否匹配FUser user = userService.getUser(phone);if(ObjectUtil.isNull(user) || !bCryptPasswordEncoder.matches(password,user.getPassword())){return RespBean.error("用户名或密码不正确,请重新输入!");}UserDetails userDetails = userDetailsService.loadUserByUsername(user.getUsername());//更新security上下文登录用户对象,null的位置本来该放密码,但是一般不放//userDetails.getAuthorities()是权限列表UsernamePasswordAuthenticationToken authentication =new UsernamePasswordAuthenticationToken(userDetails, null,userDetails.getAuthorities());// 放在security全局里面SecurityContextHolder.getContext().setAuthentication(authentication);// 到这里说明没问题 就让他拿到令牌String token = jwtTokenUtils.generateToken(userDetails);Map<String, String> tokenMap = new HashMap<>();tokenMap.put("token", token);tokenMap.put("tokenHead", tokenHead);//返回头部信息// 登录成功之后返回一个token给前端return RespBean.success("登录成功", tokenMap);//tokenMap中有 username,new Date(),tokenHead}@Overridepublic List<FRole> getRoles(String id) {return roleMapper.getRoles(id);}@Overridepublic FUser getUser(String phone) {return userService.getOne(new QueryWrapper<FUser>().eq("phone",phone));}@Overridepublic FUser getOneUser(String username) {return userService.getOne(new QueryWrapper<FUser>().eq("username",username));}}

jwt拦截器

/*** jwt登录授权过滤器*/public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {@Value("${jwt.tokenHeader}")private String tokenHeader;@Value("${jwt.tokenHead}")private String tokenHead;@Autowiredprivate JwtTokenUtils jwtTokenUtils;@Autowiredprivate UserDetailsService userDetailsService;@Overrideprotected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {//通过 request 获取请求头String authHeader = httpServletRequest.getHeader(tokenHeader);//验证头部,不存在,或者不是以tokenHead:Bearer开头的if (authHeader != null && authHeader.startsWith(tokenHead)){//存在,就做一个字符串的截取,其实就是获取了登录的tokenString authToken = authHeader.substring(tokenHead.length());//jwt根据token获取用户名//token存在用户名但是未登录String userName = jwtTokenUtils.getUserNameFromToken(authToken);if (userName != null && SecurityContextHolder.getContext().getAuthentication() == null){//登录UserDetails userDetails = userDetailsService.loadUserByUsername(userName);//判断token是否有效,如果有效把他重新放到用户对象里面if (jwtTokenUtils.validateToken(authToken,userDetails)){UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));SecurityContextHolder.getContext().setAuthentication(authenticationToken);}}}//放行filterChain.doFilter(httpServletRequest,httpServletResponse);}}

securityconfig需要继承WebSecurityConfigureAdapter

/*** security配置类**///WebSecurityConfigurerAdapter 类是个适配器, 在配置的时候,需要我们自己写个配置类去继承他,然后编写自己所特殊需要的配置@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate IAdminService adminService;@Autowiredprivate RestAuthorizationEntryPoint restAuthorizationEntryPoint;@Autowiredprivate RestfulAccessDeniedHandler restfulAccessDeniedHandler;@Autowiredprivate CustomFilter customFilter;@Autowiredprivate CustomUrlDecisionManager customUrlDecisionManager;@Override//身份验证管理生成器protected void configure(AuthenticationManagerBuilder auth) throws Exception {//重写这个方法是因为,让登录的时候请求走自己重写的登录方法 UserDetailsService userDetailsService()//userDetailsService() 获取了用户名//asswordEncoder(passwordEncoder())密码匹配是通过BCryptPasswordEncoder加密来完成的auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());// auth.userDetailsService(userDetailsService()).passwordEncoder(NoOpPasswordEncoder.getInstance());}@Overridepublic void configure(WebSecurity web) throws Exception {web.ignoring().antMatchers(//放行的资源路径"/login","/logout","/css/**","/js/**","/index.html","favicon.ico","/doc.html","/captcha","/webjars/**","/swagger-resources/**","/v2/api-docs/**","/ws/**");}//security完整的配置@Overrideprotected void configure(HttpSecurity http) throws Exception {//使用jwt不需要csrfhttp.csrf().disable()//意思 使残废,关闭后面and之前的配置//基于token存储登录用户信息,不需要session,关闭session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()//所有请求都要求认证.anyRequest().authenticated()//动态权限,获取不同菜单列表.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {@Overridepublic <O extends FilterSecurityInterceptor> O postProcess(O o) {o.setAccessDecisionManager(customUrlDecisionManager);o.setSecurityMetadataSource(customFilter);return o;}}).and()//禁用缓存.headers().cacheControl();//添加 jwt 登录授权拦截器http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);//添加自定义 未授权 和 未登录 结果返回http.exceptionHandling()//自定义 未授权.accessDeniedHandler(restfulAccessDeniedHandler)//自定义 未登录结果返回.authenticationEntryPoint(restAuthorizationEntryPoint);}@Override//重写获取用户的方法@Beanpublic UserDetailsService userDetailsService(){return username -> {Admin admin = adminService.getAdminByUserName(username);if (admin != null){admin.setRoles(adminService.getRoles(admin.getId()));return admin;}throw new UsernameNotFoundException("用户名或密码不正确!");};}@Beanpublic PasswordEncoder passwordEncoder(){//Security中默认的密码实现 BCryptPasswordEncoderreturn new BCryptPasswordEncoder();}//拦截器@Beanpublic JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){return new JwtAuthenticationTokenFilter();}}

权限控制过滤器

/*** 权限控制* 根据请求url分析请求所需的角色*/@Componentpublic class CustomFilter implements FilterInvocationSecurityMetadataSource {@Autowiredprivate IFMenuService menuService;AntPathMatcher antPathMatcher = new AntPathMatcher();@Overridepublic Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {//获取请求的urlString requestUrl = ((FilterInvocation) object).getRequestUrl();//根据角色去查询所有的菜单List<FMenu> menus = menuService.getMenuRoleList();//同时查询所有菜单的权限List<FMenu> menusAll = menuService.list();for (FMenu fMenu : menusAll) {if(fMenu.getUrl().equals(requestUrl)){for (FMenu menu : menus){//判断请求 url 与菜单角色是否匹配,如果这个url在菜单中存在但是没有匹配上就直接抛异常if (antPathMatcher.match(menu.getUrl(),requestUrl)){String[] strings = menu.getRoles().stream().map(FRole::getName).toArray(String[]::new);return SecurityConfig.createList(strings);}}throw new AccessDeniedException("权限不足,请联系管理员!");}}//没匹配的 url 默认登录就可以访问return SecurityConfig.createList("ROLE_LOGIN");}@Overridepublic Collection<ConfigAttribute> getAllConfigAttributes() {return null;}@Overridepublic boolean supports(Class<?> aClass) {return false;}}

根据角色去匹配对应的url是否有权限

/*** @description: 判断用户角色* @author: Honors* @create: -07-14 14:29*/@Slf4j@Componentpublic class CustomUrlDecisionManager implements AccessDecisionManager {@Overridepublic void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {for (ConfigAttribute configAttribute : configAttributes) {//当前 url 所需要的角色String needRole = configAttribute.getAttribute();if ("ROLE_LOGIN".equals(needRole)){if (authentication instanceof AnonymousAuthenticationToken){throw new AccessDeniedException("尚未登录,请登录!");}else {throw new AccessDeniedException("权限不足,请联系管理员!");}}//判断用户角色是否为url所需要角色Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();for (GrantedAuthority authority : authorities) {log.info("当前authority:"+authority.getAuthority());if (authority.getAuthority().equals(needRole)){return;}}}throw new AccessDeniedException("权限不足,请联系管理员!");}@Overridepublic boolean supports(ConfigAttribute configAttribute) {return false;}@Overridepublic boolean supports(Class<?> aClass) {return false;}}

自定义序列化

/*** @description: 自定义authority字段解析器* @author: Honors*/public class CustomAuthorityDeserializer extends JsonDeserializer {@Overridepublic Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {ObjectMapper mapper = (ObjectMapper) p.getCodec();JsonNode jsonNode = mapper.readTree(p);List<GrantedAuthority> grantedAuthorities = new LinkedList<>();Iterator<JsonNode> elements = jsonNode.elements();while (elements.hasNext()){JsonNode next = elements.next();//找到authority字段JsonNode authority = next.get("authority");//序列号,让json可以解析grantedAuthorities.add(new SimpleGrantedAuthority(authority.asText()));}return grantedAuthorities;}}

Security自定义返回结果

/*** 当未登录或者token失效时访问接口是,自定义返回结果*/@Componentpublic class RestAuthorizationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {response.setCharacterEncoding("UTF-8");//设置数据格式为json格式response.setContentType("application/json");//拿到输出流PrintWriter out = response.getWriter();//未登录或失效RespBean bean = RespBean.error("未登录或用户信息过期,请重新登录!");bean.setCode(401);out.write(new ObjectMapper().writeValueAsString(bean));out.flush();out.close();}}

/*** 自定义授权* 当访问接口没有权限时,自定义返回结果*/@Componentpublic class RestfulAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {response.setCharacterEncoding("UTF-8");response.setContentType("application/json");PrintWriter out = response.getWriter();RespBean error = RespBean.error("权限不足,请联系管理员!");error.setCode(403);out.write(new ObjectMapper().writeValueAsString(error));out.flush();out.close();}}

根据用户id查找角色,便于后面拿角色与根据url请求的角色做对比

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-////DTD Mapper 3.0//EN" "/dtd/mybatis-3-mapper.dtd"><mapper namespace="wqm.store.mapper.FRoleMapper"><!-- 通用查询映射结果 --><resultMap id="BaseResultMap" type="wqm.store.pojo.FRole"><id column="id" property="id" /><result column="name" property="name" /></resultMap><!-- 通用查询结果列 --><sql id="Base_Column_List">id, name</sql><select id="getRoles" resultMap="getRoles" parameterType="String">select r.id,r.name from f_user_role ur,f_role r where ur.uid = #{id}and ur.rid = r.id</select><resultMap id="getRoles" type="FRole" extends="BaseResultMap"></resultMap></mapper>

@Repositorypublic interface FRoleMapper extends BaseMapper<FRole> {List<FRole> getRoles(@Param("id")String id);}

public interface IFUserService extends IService<FUser> {RespBean loginUser(String phone, String password, HttpServletRequest request);FUser getUser(String phone);FUser getOneUser(String username);List<FRole> getRoles(String id);}

根据url查询所需角色

<select id="getMenus" resultMap="getMenus">select m.*,r.id as rid,r.name from f_role r, f_menu_role mr,f_menu m where r.id = mr.rid and mr.mid = m.id;</select><resultMap id="getMenus" type="FMenu" extends="BaseResultMap"><collection property="roles" ofType="FRole"><id property="id" column="rid"/><result property="name" column="name"/></collection></resultMap>

@Repositorypublic interface FMenuMapper extends BaseMapper<FMenu> {List<FMenu> getMenus();}

public interface IFMenuService extends IService<FMenu> {List<FMenu> getMenuRoleList();}

@Servicepublic class FMenuServiceImpl extends ServiceImpl<FMenuMapper, FMenu> implements IFMenuService {@Autowiredprivate FMenuMapper menuMapper;@Overridepublic List<FMenu> getMenuRoleList() {return menuMapper.getMenus();}}

Swagger配置,添加authrozation字段用来存放token

@Configuration@EnableSwagger2public class SwaggerConfig {@Bean//规定扫描哪些包下面生成swagger2文档public Docket createRestApi(){return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())//选择扫面哪个包.select().apis(RequestHandlerSelectors.basePackage("wqm.store.api.controller"))//所有的路径都可以.paths(PathSelectors.any()).build()//给swagger2令牌,不然测试接口太繁琐,需要登录会被拦截.securityContexts(securityContexts())//全局.securitySchemes(securitySchemes());//安全计划}private ApiInfo apiInfo(){return new ApiInfoBuilder()//标题.title("接口文档")//描述.description("").contact(new Contact("魏青冕","http://localhost:8080/doc.html","3139596057@")).version("1.0").build();}private List<ApiKey> securitySchemes(){//设置请求头信息List<ApiKey> result = new ArrayList<>();//令牌ApiKey apikey = new ApiKey("authorization","authorization","Header");result.add(apikey);return result;}private List<SecurityContext> securityContexts(){//设置需要登录认证的路径List<SecurityContext> result = new ArrayList<>();result.add(getContextBypath("/test3/.*"));return result;}private SecurityContext getContextBypath(String pathRegex) {return SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex(pathRegex)).build();}private List<SecurityReference> defaultAuth() {List<SecurityReference> result = new ArrayList<>();AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];authorizationScopes[0] = authorizationScope;result.add(new SecurityReference("Authorization",authorizationScopes));return result;}}

测试如下

3.RBAC模型设计

/*Navicat Premium Data TransferSource Server : 丫丫Source Server Type : MySQLSource Server Version : 80028Source Host : localhost:3306Source Schema : fishstoreTarget Server Type : MySQLTarget Server Version : 80028File Encoding : 65001Date: 09/08/ 13:28:21*/SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0;-- ------------------------------ Table structure for f_menu-- ----------------------------DROP TABLE IF EXISTS `f_menu`;CREATE TABLE `f_menu` (`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,`url` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of f_menu-- ----------------------------INSERT INTO `f_menu` VALUES ('67796ddf8305e03625ebdba3195ec312', '/test1');INSERT INTO `f_menu` VALUES ('b443e9ad4898f4e5897274371562df76', '/test2');-- ------------------------------ Table structure for f_menu_role-- ----------------------------DROP TABLE IF EXISTS `f_menu_role`;CREATE TABLE `f_menu_role` (`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,`rid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`mid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of f_menu_role-- ----------------------------INSERT INTO `f_menu_role` VALUES ('db268eac1fc15596e175b46683066cb8', 'ab363ec9a5766ee42b15fc554d2e7c21', '67796ddf8305e03625ebdba3195ec312');-- ------------------------------ Table structure for f_role-- ----------------------------DROP TABLE IF EXISTS `f_role`;CREATE TABLE `f_role` (`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,`name` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of f_role-- ----------------------------INSERT INTO `f_role` VALUES ('ab363ec9a5766ee42b15fc554d2e7c21', 'ROLE_stu');-- ------------------------------ Table structure for f_user-- ----------------------------DROP TABLE IF EXISTS `f_user`;CREATE TABLE `f_user` (`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户唯一标识',`username` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名',`phone` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '手机号',`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码',PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of f_user-- ----------------------------INSERT INTO `f_user` VALUES ('1ef48d092db370165b8e4cdfac9a0187', 'cjj', '13456789457', '$2a$10$ogvUqZZAxrBwrmVI/e7.SuFYyx8my8d.9zJ6bs9lPKWvbD9eefyCe');INSERT INTO `f_user` VALUES ('2ff299d16d007aa37007394bae9bbcac', '会飞的鱼', '15295675946', '$2a$10$ogvUqZZAxrBwrmVI/e7.SuFYyx8my8d.9zJ6bs9lPKWvbD9eefyCe');-- ------------------------------ Table structure for f_user_role-- ----------------------------DROP TABLE IF EXISTS `f_user_role`;CREATE TABLE `f_user_role` (`id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,`uid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户主键',`rid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '角色主键',PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of f_user_role-- ----------------------------INSERT INTO `f_user_role` VALUES ('695208cf31b61627c00bd987cfdd22e7', '2ff299d16d007aa37007394bae9bbcac', 'ab363ec9a5766ee42b15fc554d2e7c21');SET FOREIGN_KEY_CHECKS = 1;

定义参考:RBAC权限模型[完整] - 简书 ()

如果觉得《springsecurity整合jwt实现授权认证 权限分配》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。