| 用户表 ( sys_user ):保存用户信息 |
| 角色表 ( sys_role ):保存角色信息 |
| 权限表 ( sys_permission ):保存系统资源信息。如:菜单、按钮 和对应 URL它们的关系 :用户表与角色表是 多对多关系 ,角色表与资源表是多对多关系。 |
| 用户角色关系表(sys_user_role):用于维护用户和角色的关系 |
| 角色资源关系表(sys_role_permission):用于维护角色与资源的关系 |

-
导入数据库

-
步骤
| # core模块导入依赖 |
| <dependency> |
| <groupId>org.springframework.boot</groupId> |
| <artifactId>spring-boot-starter-jdbc</artifactId> |
| </dependency> |
| <dependency> |
| <groupId>mysql</groupId> |
| <artifactId>mysql-connector-java</artifactId> |
| </dependency> |
| |
| # web模块导入依赖 |
| |
| <dependency> |
| <groupId>com.baomidou</groupId> |
| <artifactId>mybatis-plus-boot-starter</artifactId> |
| </dependency> |
| |
| <dependency> |
| <groupId>com.alibaba</groupId> |
| <artifactId>druid</artifactId> |
| </dependency> |
| |
| # web模块配置yml |
| spring: |
| datasource: |
| username: root |
| password: 123456 |
| url: jdbc:mysql://127.0.0.1:3306/demo?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8 |
| #mysql8版本以上驱动包指定新的驱动类 |
| driver-class-name: com.mysql.cj.jdbc.Driver |
| # 数据源其他配置, 在 DruidConfig配置类中手动绑定 |
| initialSize: 8 |
| minIdle: 5 |
| maxActive: 20 |
| maxWait: 60000 |
| timeBetweenEvictionRunsMillis: 60000 |
| minEvictableIdleTimeMillis: 300000 |
| validationQuery: SELECT 1 FROM DUAL |
| mybatis-plus: |
| # 指定实体类所有包 |
| type-aliases-package: com.ychen.security.model |
| # 日志级别,会打印sql语句 |
| logging: |
| level: |
| com.ychen.security.mapper: debug |
| |
| # 数据库连接池配置类 |
| @Configuration |
| public class DruidConfig { |
| @ConfigurationProperties(prefix = "spring.datasource") |
| @Bean |
| public DataSource dataSource() { |
| return new DruidDataSource(); |
| } |
| } |
| |
| # mybatis plus配置类 |
| @EnableTransactionManagement // 开启事务管理 |
| @MapperScan("com.ychen.security.mapper") // 扫描Mapper接口 |
| @Configuration |
| public class MybatisPlusConfig { |
| /** |
| * 分页插件 |
| * @return |
| */ |
| @Bean |
| public PaginationInterceptor paginationInterceptor() { |
| return new PaginationInterceptor(); |
| } |
| } |
| |
| # 测试是否配置成功,启动未报错 |
| @Data |
| public class SysUser implements UserDetails { |
| |
| @TableId(type = IdType.AUTO) |
| private Long id; |
| |
| private String username; |
| |
| |
| |
| |
| private String password; |
| |
| |
| |
| |
| |
| |
| private boolean isAccountNonExpired = true; |
| |
| private boolean isAccountNonLocked = true; |
| |
| private boolean isCredentialsNonExpired = true; |
| |
| private boolean isEnabled = true; |
| |
| |
| |
| |
| @TableField(exist = false) |
| private Collection<? extends GrantedAuthority> authorities; |
| |
| private String nickName; |
| |
| private String mobile; |
| |
| private String email; |
| |
| private String createDate; |
| |
| private String updateDate; |
| |
| |
| |
| |
| @TableField(exist = false) |
| private List<com.ychen.security.model.SysRole> roleList = Lists.newArrayList(); |
| |
| |
| |
| |
| @TableField(exist = false) |
| private List<Long> roleIds = Lists.newArrayList(); |
| public List<Long> getRoleIds() { |
| if(CollectionUtils.isNotEmpty(roleList)) { |
| roleIds = Lists.newArrayList(); |
| for(com.ychen.security.model.SysRole role : roleList) { |
| roleIds.add(role.getId()); |
| } |
| } |
| return roleIds; |
| } |
| |
| |
| |
| |
| @TableField(exist = false) |
| private List<com.ychen.security.model.SysPermission> permissions = Lists.newArrayList(); |
| |
| } |
| |
| @Data |
| public class SysRole implements Serializable { |
| |
| @TableId(type = IdType.AUTO) |
| private Long id; |
| |
| |
| |
| |
| private String name; |
| |
| |
| |
| |
| private String remark; |
| |
| private Date createDate; |
| |
| private Date updateDate; |
| |
| |
| |
| |
| |
| @TableField(exist = false) |
| private List<com.ychen.security.model.SysPermission> perList = Lists.newArrayList(); |
| |
| |
| |
| |
| |
| @TableField(exist = false) |
| private List<Long> perIds = Lists.newArrayList(); |
| |
| public List<Long> getPerIds() { |
| if(CollectionUtils.isNotEmpty(perList)) { |
| perIds = Lists.newArrayList(); |
| for(com.ychen.security.model.SysPermission per : perList) { |
| perIds.add(per.getId()); |
| } |
| } |
| return perIds; |
| } |
| |
| } |
| |
| @Data |
| public class SysPermission implements Serializable { |
| |
| @TableId(type = IdType.AUTO) |
| private Long id; |
| |
| |
| |
| |
| |
| private Long parentId = 0L; |
| |
| |
| |
| |
| @TableField(exist = false) |
| private String parentName = "根菜单"; |
| |
| private String name; |
| |
| private String code; |
| |
| private String url; |
| |
| |
| |
| |
| private Integer type; |
| |
| private String icon; |
| |
| private String remark; |
| |
| private Date createDate; |
| |
| private Date updateDate; |
| |
| |
| |
| |
| |
| @TableField(exist = false) |
| private List<SysPermission> children; |
| |
| |
| |
| |
| |
| @TableField(exist = false) |
| private List<String> childrenUrl; |
| |
| } |
| # mapper |
| public interface SysUserMapper extends BaseMapper<SysUser> { |
| |
| } |
| |
| # service |
| public interface SysUserService extends IService<SysUser> { |
| |
| } |
| |
| @Service |
| public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService { |
| |
| } |
| |
| # controller测试 |
| @RestController |
| public class TestController2 { |
| |
| @Autowired |
| SysUserService sysUserService; |
| |
| @GetMapping("/getTest") |
| public String getTest(){ |
| List<SysUser> list = sysUserService.list(); |
| System.out.println(list); |
| return "success"; |
| } |
| |
| } |
| # 业务层接口 |
| public interface SysUserService extends IService<SysUser> { |
| |
| |
| |
| |
| |
| |
| SysUser findByUsername(String username) ; |
| |
| } |
| |
| # 业务层实现类 |
| @Service |
| public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService { |
| |
| @Override |
| public SysUser findByUsername(String username) { |
| if(StringUtils.isEmpty(username)) { |
| return null; |
| } |
| QueryWrapper queryWrapper = new QueryWrapper(); |
| queryWrapper.eq("username", username); |
| |
| return baseMapper.selectOne(queryWrapper); |
| } |
| |
| } |
| |
| # 控制层 |
| @RestController |
| @RequestMapping("/test") |
| public class TestController2 { |
| |
| @Autowired |
| SysUserService sysUserService; |
| |
| |
| @GetMapping("/test2") |
| public String test2(){ |
| SysUser user = sysUserService.findByUsername("admin"); |
| System.out.println("user: " + user); |
| return "success"; |
| } |
| |
| } |
| |
| # 控制台 |
| 11:24:13.599 DEBUG 20080 --- [p-nio-80-exec-1] c.y.s.mapper.SysUserMapper.selectOne : ==> Preparing: SELECT id,update_date,nick_name,mobile,is_account_non_locked,password,is_account_non_expired,is_credentials_non_expired,is_enabled,email,username,create_date FROM sys_user WHERE (username = ?) |
| 11:24:13.618 DEBUG 20080 --- [p-nio-80-exec-1] c.y.s.mapper.SysUserMapper.selectOne : ==> Parameters: admin(String) |
| 11:24:13.651 DEBUG 20080 --- [p-nio-80-exec-1] c.y.s.mapper.SysUserMapper.selectOne : <== Total: 1 |
| user: SysUser(id=9, username=admin, password=$2a$10$rDkPvvAFV8kqwvKJzwlRv.i.q.wz1w1pz0SFsHn/55jNeZFQv/eCm, isAccountNonExpired=true, isAccountNonLocked=true, isCredentialsNonExpired=true, isEnabled=true, authorities=null, nickName=梦学谷, mobile=16888888888, email=mengxu |
| # mapper |
| public interface SysRoleMapper extends BaseMapper<SysRole> { |
| |
| } |
| |
| # 业务层接口 |
| public interface SysRoleService extends IService<SysRole> { |
| |
| } |
| |
| # 业务层实现 |
| @Service |
| public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements SysRoleService { |
| |
| } |
| |
| # 接口 |
| @Autowired |
| SysRoleService sysRoleService; |
| |
| |
| |
| |
| @GetMapping("/test3") |
| public String test3(){ |
| SysRole role = sysRoleService.getById(9); |
| System.out.println("role:" + role); |
| return "success"; |
| } |
| |
| # 控制台 |
| 11:52:35.391 DEBUG 11852 --- [p-nio-80-exec-3] c.y.s.mapper.SysRoleMapper.selectById : ==> Preparing: SELECT id,update_date,name,remark,create_date FROM sys_role WHERE id=? |
| 11:52:35.392 DEBUG 11852 --- [p-nio-80-exec-3] c.y.s.mapper.SysRoleMapper.selectById : ==> Parameters: 9(Integer) |
| 11:52:35.414 DEBUG 11852 --- [p-nio-80-exec-3] c.y.s.mapper.SysRoleMapper.selectById : <== Total: 1 |
| role:SysRole(id=9, name=超级管理员, remark=拥有所有的权限, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Tue Aug 08 11:11:11 GMT+08:00 2023, perList=[], perIds=[]) |
| # mapper |
| public interface SysPermissionMapper extends BaseMapper<SysPermission> { |
| |
| } |
| |
| # 业务层接口 |
| public interface SysPermissionService extends IService<SysPermission> { |
| |
| } |
| |
| # 业务层实现 |
| @Service |
| public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements SysPermissionService { |
| |
| } |
| |
| # 控制层接口 |
| @Autowired |
| SysPermissionService sysPermissionService; |
| |
| @GetMapping("/test4") |
| public String test4(){ |
| SysPermission permissions = sysPermissionService.getById(29); |
| System.out.println("permissions:" + permissions); |
| return "success"; |
| } |
| |
| # 控制台 |
| 11:50:03.198 DEBUG 11852 --- [p-nio-80-exec-1] c.y.s.m.SysPermissionMapper.selectById : ==> Preparing: SELECT id,update_date,code,icon,remark,type,parent_id,url,name,create_date FROM sys_permission WHERE id=? |
| 11:50:03.210 DEBUG 11852 --- [p-nio-80-exec-1] c.y.s.m.SysPermissionMapper.selectById : ==> Parameters: 29(Integer) |
| 11:50:03.266 DEBUG 11852 --- [p-nio-80-exec-1] c.y.s.m.SysPermissionMapper.selectById : <== Total: 1 |
| permissions:SysPermission(id=29, parentId=28, parentName=根菜单, name=列表, code=sys:permission:list, url=null, type=2, icon=null, remark=权限列表, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Tue Aug 08 11:11:11 GMT+08:00 2023, |
| # mapper |
| public interface SysPermissionMapper extends BaseMapper<SysPermission> { |
| |
| // 根据用户id查询用户所拥有的权限 |
| List<SysPermission> selectPermissionByUserId(@Param("userId") Long userId); |
| |
| } |
| |
| <!DOCTYPE mapper |
| PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" |
| "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| <mapper namespace="com.ychen.security.mapper.SysPermissionMapper"> |
| |
| <select id="selectPermissionByUserId" resultType="SysPermission"> |
| SELECT DISTINCT |
| p.id, |
| p.parent_id, |
| p. NAME, |
| p. CODE, |
| p.url, |
| p.type, |
| p.icon, |
| p.remark, |
| p.create_date, |
| p.update_date |
| FROM |
| sys_user AS u |
| LEFT JOIN sys_user_role AS ur ON u.id = ur.user_id |
| LEFT JOIN sys_role AS r ON ur.role_id = r.id |
| LEFT JOIN sys_role_permission AS rp ON rp.role_id = r.id |
| LEFT JOIN sys_permission AS p ON rp.permission_id = p.id |
| WHERE |
| u.id = #{userId} |
| </select> |
| |
| </mapper> |
| |
| # 业务层接口 |
| public interface SysPermissionService extends IService<SysPermission> { |
| |
| /** |
| * 通过用户id查询所拥有权限 |
| * @param userId |
| * @return |
| */ |
| List<SysPermission> findByUserId(Long userId); |
| |
| } |
| |
| # 业务层实现 |
| @Service |
| public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements SysPermissionService { |
| |
| @Override |
| public List<SysPermission> findByUserId(Long userId) { |
| if(userId == null) { |
| return null; |
| } |
| List<SysPermission> permissionList = baseMapper.selectPermissionByUserId(userId); |
| // 如果没有权限,则将集合中的数据null移除 |
| permissionList.remove(null); |
| return permissionList; |
| } |
| |
| } |
| |
| # 控制层接口 |
| @RestController |
| @RequestMapping("/test") |
| public class TestController2 { |
| |
| @Autowired |
| SysPermissionService sysPermissionService; |
| |
| @GetMapping("/test5") |
| public String test5(){ |
| List<SysPermission> permissions = sysPermissionService.findByUserId(9L); |
| System.out.println(permissions); |
| System.out.println("permissions:" + permissions.size()); |
| return "success"; |
| } |
| |
| } |
| |
| # 控制台 |
| 13:23:56.820 DEBUG 19664 |
| 13:23:56.831 DEBUG 19664 |
| 13:23:56.867 DEBUG 19664 |
| [SysPermission(id=11, parentId=0, parentName=根菜单, name=首页, code=sys:index, url=/, type=1, icon=fa fa-dashboard, remark=, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=17, parentId=0, parentName=根菜单, name=系统管理, code=sys:manage, url=null, type=1, icon=fa fa-cogs, remark=null, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=18, parentId=17, parentName=根菜单, name=用户管理, code=sys:user, url=/user, type=1, icon=fa fa-users, remark=null, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=19, parentId=18, parentName=根菜单, name=列表, code=sys:user:list, url=, type=2, icon=, remark=员工列表, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Tue Aug 08 11:11:11 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=20, parentId=18, parentName=根菜单, name=新增, code=sys:user:add, url=, type=2, icon=, remark=新增用户, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=21, parentId=18, parentName=根菜单, name=修改, code=sys:user:edit, url=, type=2, icon=, remark=修改用户, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=22, parentId=18, parentName=根菜单, name=删除, code=sys:user:delete, url=, type=2, icon=, remark=删除用户, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=23, parentId=17, parentName=根菜单, name=角色管理, code=sys:role, url=/role, type=1, icon=fa fa-user-secret, remark=null, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=24, parentId=23, parentName=根菜单, name=列表, code=sys:role:list, url=null, type=2, icon=null, remark=角色列表, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Tue Aug 08 11:11:11 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=25, parentId=23, parentName=根菜单, name=新增, code=sys:role:add, url=, type=2, icon=, remark=新增角色, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=26, parentId=23, parentName=根菜单, name=修改, code=sys:role:edit, url=, type=2, icon=, remark=修改角色, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=27, parentId=23, parentName=根菜单, name=删除, code=sys:role:delete, url=, type=2, icon=, remark=删除角色, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=28, parentId=17, parentName=根菜单, name=权限管理, code=sys:permission, url=/permission, type=1, icon=fa fa-cog, remark=null, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=29, parentId=28, parentName=根菜单, name=列表, code=sys:permission:list, url=null, type=2, icon=null, remark=权限列表, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Tue Aug 08 11:11:11 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=30, parentId=28, parentName=根菜单, name=新增, code=sys:permission:add, url=, type=2, icon=null, remark=新增权限, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=31, parentId=28, parentName=根菜单, name=修改, code=sys:permission:edit, url=, type=2, icon=null, remark=修改权限, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null), SysPermission(id=32, parentId=28, parentName=根菜单, name=删除, code=sys:permission:delete, url=, type=2, icon=, remark=删除权限, createDate=Tue Aug 08 11:11:11 GMT+08:00 2023, updateDate=Wed Aug 09 15:26:28 GMT+08:00 2023, children=null, childrenUrl=null)] |
| permissions:17 |
| @Component("customUserDetailsService") |
| public class CustomUserDetailsService implements UserDetailsService { |
| |
| |
| Logger logger = LoggerFactory.getLogger(getClass()); |
| |
| |
| @Autowired |
| PasswordEncoder passwordEncoder; |
| |
| |
| @Autowired |
| SysUserService sysUserService; |
| |
| |
| @Autowired |
| SysPermissionService sysPermissionService; |
| |
| @Override |
| public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { |
| logger.info("请求认证的用户名: " + username); |
| |
| SysUser sysUser = sysUserService.findByUsername(username); |
| |
| if(sysUser == null) { |
| throw new UsernameNotFoundException("用户名或密码错误"); |
| } |
| |
| List<SysPermission> permissions = sysPermissionService.findByUserId(sysUser.getId()); |
| |
| if(CollectionUtils.isEmpty(permissions)) { |
| return sysUser; |
| } |
| |
| |
| |
| |
| sysUser.setPermissions(permissions); |
| |
| List<GrantedAuthority> authorities = Lists.newArrayList(); |
| for(SysPermission sp: permissions) { |
| |
| String code = sp.getCode(); |
| authorities.add(new SimpleGrantedAuthority(code)); |
| } |
| |
| sysUser.setAuthorities(authorities); |
| |
| return sysUser; |
| } |
| |
| } |
| # 业务层接口 |
| public interface SysUserService extends IService<SysUser> { |
| |
| |
| |
| |
| |
| |
| SysUser findByMobile(String mobile); |
| |
| } |
| |
| # 业务层实现 |
| @Service |
| public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService { |
| |
| @Override |
| public SysUser findByMobile(String mobile) { |
| if(StringUtils.isEmpty(mobile)) { |
| return null; |
| } |
| QueryWrapper queryWrapper = new QueryWrapper(); |
| queryWrapper.eq("mobile", mobile); |
| |
| return baseMapper.selectOne(queryWrapper); |
| } |
| |
| } |
| |
| # 实现UserDetailsService接口 |
| @Component("mobileUserDetailsService") |
| public class MobileUserDetailsService implements UserDetailsService { |
| |
| |
| Logger logger = LoggerFactory.getLogger(getClass()); |
| |
| |
| @Autowired |
| SysUserService sysUserService; |
| |
| |
| @Autowired |
| SysPermissionService sysPermissionService; |
| |
| @Override |
| public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException { |
| logger.info("请求的手机号是:" + mobile); |
| |
| SysUser sysUser = sysUserService.findByMobile(mobile); |
| |
| if(sysUser == null) { |
| throw new UsernameNotFoundException("该手机号未注册"); |
| } |
| |
| List<SysPermission> permissions = sysPermissionService.findByUserId(sysUser.getId()); |
| |
| if(CollectionUtils.isEmpty(permissions)) { |
| return sysUser; |
| } |
| |
| |
| |
| |
| sysUser.setPermissions(permissions); |
| |
| List<GrantedAuthority> authorities = Lists.newArrayList(); |
| for(SysPermission sp: permissions) { |
| |
| String code = sp.getCode(); |
| authorities.add(new SimpleGrantedAuthority(code)); |
| } |
| |
| sysUser.setAuthorities(authorities); |
| |
| return sysUser; |
| } |
| |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术