更换网站标题深圳大型互联网公司

张小明 2025/12/29 18:27:03
更换网站标题,深圳大型互联网公司,深圳宝安区属于什么风险区,阿里巴巴网站怎样做的漂亮授权授权是独立于认证的存在认证是负责如何登录#xff0c;认证成功 登录成功认证成功之后#xff0c;能访问哪些接口#xff0c;哪些方法认证方式的不同#xff0c;不会影响授权认证成功之后#xff0c;能做什么能访问什么#xff0c;是由授权决定的查看授权的配置授权…授权授权是独立于认证的存在认证是负责如何登录认证成功 登录成功认证成功之后能访问哪些接口哪些方法认证方式的不同不会影响授权认证成功之后能做什么能访问什么是由授权决定的查看授权的配置授权列表的来源是UserDetails在登录的时候在UserDetailsService中查询出来并赋值的想要给授权列表赋值需要更改登录的逻辑一、准备工作在登录的时候查询出用户的角色信息 菜单信息角色授权授权码授权1、生成代码根据数据库生成三张表的代码2、重新修改登录接口AdminUserServiceOverride public AdminUser getByUsername(String username) { LambdaQueryWrapperAdminUser queryWrapper new LambdaQueryWrapper(); queryWrapper.eq(AdminUser::getUsername,username); AdminUser adminUser getOne(queryWrapper); if (adminUser ! null){ AdminRole role roleService.getByRid(adminUser.getRoleId().intValue()); adminUser.setAdminRole(role); } return adminUser; }AdminRoleServiceService(adminRoleService) public class AdminRoleServiceImpl extends ServiceImplAdminRoleDao, AdminRole implements AdminRoleService { ​ Resource AdminMenuService adminMenuService; ​ Override public AdminRole getByRid(Integer uid) { AdminRole adminRole getById(uid); if (adminRole ! null){ //查询菜单的信息 ListAdminMenu menuList adminMenuService.getListByRid(adminRole.getRid()); adminRole.setMenuList(menuList); } return adminRole; } }AdminMenuDaopublic interface AdminMenuDao extends BaseMapperAdminMenu { ​ Select(select menu.* from admin_menu menu,rel_admin_role_menu rel where menu.mid rel.mid and rel.rid #{rid} ) ListAdminMenu selectListByRid(Integer rid); }AdminMenuServiceService(adminMenuService) public class AdminMenuServiceImpl extends ServiceImplAdminMenuDao, AdminMenu implements AdminMenuService { Resource AdminMenuDao adminMenuDao; ​ Override public ListAdminMenu getListByRid(Integer rid) { ListAdminMenu allList adminMenuDao.selectListByRid(rid); //打算区分父子级 //获取1级菜单 ListAdminMenu oneList allList.stream() .filter(adminMenu - adminMenu.getPid() -1) .toList(); oneList.forEach(one - { //获取当前循环的1级菜单的子菜单 ListAdminMenu childList allList.stream().map(adminMenu - { if (one.getMid().equals(adminMenu.getPid())) { return adminMenu; } return null; }).filter(Objects::nonNull).toList(); one.setChildList(childList); }); return oneList; } }AdminMenuServic---AI进化版Service(adminMenuService) public class AdminMenuServiceImpl extends ServiceImplAdminMenuDao, AdminMenu implements AdminMenuService { Resource AdminMenuDao adminMenuDao; ​ Override public ListAdminMenu getListByRid(Integer rid) { ListAdminMenu allList adminMenuDao.selectListByRid(rid); // 使用stream流操作将allList按照父子级分离 // 先按pid分组 MapInteger, ListAdminMenu menuMap allList.stream() .collect(Collectors.groupingBy(AdminMenu::getPid)); // 获取一级菜单pid为-1的菜单 ListAdminMenu oneList menuMap.getOrDefault(-1, List.of()); // 为每个一级菜单设置子菜单列表 oneList.forEach(one - { one.setChildList(menuMap.getOrDefault(one.getMid(), List.of())); }); return oneList; } }3、修改UserDetails的授权方法Override public Collection? extends GrantedAuthority getAuthorities() { ListGrantedAuthority list new ArrayList(); //根据角色授权 AdminRole adminRole adminUser.getAdminRole(); if (adminRole ! null){ GrantedAuthority authority new SimpleGrantedAuthority(ROLE_ adminRole.getCode()); list.add(authority); } //存储授权列表 return list; }二、测试角色授权编写测试接口提前明确哪个角色可以访问 哪个接口。如果一个接口写完了之后没有配置权限表明所有已经认证的用户都可以访问1、已有接口/game/f1/game/f2/game/f32、已有角色admintest3、设计权限只有admin角色的用户可以访问f1方法只有test角色的用户可以访问f2方法只有拥有admin或者test可以访问f3方法4、实现设计修改配置类Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { .... http.authorizeHttpRequests(auth - auth //只有admin角色的用户可以访问f1方法 .requestMatchers(/game/f1).hasRole(admin) //只有test角色的用户可以访问f2方法 .requestMatchers(/game/f2).hasRole(test) //只有拥有admin或者test可以访问f3方法 .requestMatchers(/game/f3).hasAnyRole(admin,test) .requestMatchers(/loginpage.html, /login/**, /jsonlogin, /phoneLogin) .permitAll() .anyRequest() .authenticated() //其他页面要登录之后才能访问 );//放过登录接口以及静态页面 return http.build(); .... }三、角色的继承设计让test拥有的权限admin也拥有admin 拥有 test的权限// 角色继承配置 Bean public RoleHierarchy roleHierarchy(){ RoleHierarchyImpl hierarchy new RoleHierarchyImpl(); hierarchy.setHierarchy(ROLE_admin ROLE_test); return hierarchy; } //支持角色继承的授权管理器 public AuthorityAuthorizationManagerRequestAuthorizationContext testRoleAuthorizationManager(){ //通过静态方法创建实例再绑定角色来继承 AuthorityAuthorizationManagerRequestAuthorizationContext manager AuthorityAuthorizationManager.hasRole(test); manager.setRoleHierarchy(roleHierarchy()); return manager; }http.authorizeHttpRequests(auth - auth .requestMatchers(/game/f2).access(testRoleAuthorizationManager()) );//放过登录接口以及静态页面完整配置// 角色继承配置 Bean public RoleHierarchy roleHierarchy(){ RoleHierarchyImpl hierarchy new RoleHierarchyImpl(); hierarchy.setHierarchy(ROLE_admin ROLE_test); return hierarchy; } //支持角色继承的授权管理器 public AuthorityAuthorizationManagerRequestAuthorizationContext testRoleAuthorizationManager(){ //通过静态方法创建实例再绑定角色来继承 AuthorityAuthorizationManagerRequestAuthorizationContext manager AuthorityAuthorizationManager.hasRole(test); manager.setRoleHierarchy(roleHierarchy()); return manager; } Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.cors(cors - cors.configurationSource(corsConfigurationSource())); http.securityContext(context - context.securityContextRepository(securityContextRepository())); //因为当前json登录功能和用户名密码登录功能类似 // 所以把jsonfilter放到UsernamePasswordAuthenticaitonFilter相同的位置 http.addFilterAt(jsonFilter(), UsernamePasswordAuthenticationFilter.class); http.addFilterAt(phoneFilter(), UsernamePasswordAuthenticationFilter.class); //关闭csrf 跨域请求伪造的控制 http.csrf(csrf - csrf.disable()); http.authorizeHttpRequests(auth - auth //只有admin角色的用户可以访问f1方法 .requestMatchers(/game/f1).hasRole(admin) //只有test角色的用户可以访问f2方法 //.requestMatchers(/game/f2).hasRole(test) .requestMatchers(/game/f2).access(testRoleAuthorizationManager()) //只有拥有admin或者test可以访问f3方法 .requestMatchers(/game/f3).hasAnyRole(admin,test) .requestMatchers(/loginpage.html, /login/**, /jsonlogin, /phoneLogin) .permitAll() .anyRequest() .authenticated() //其他页面要登录之后才能访问 );//放过登录接口以及静态页面 // ↓配置表单提交 http.formLogin(form - { // 确保认证信息被正确设置并保存到session中 form.loginPage(/loginpage.html) //自定义登录页面的路径 .loginProcessingUrl(/javasmlogin) //表单提交的路径 .usernameParameter(uname) //自定义用户名的参数名默认是username .passwordParameter(pwd) //Authentication 是 UsernamePasswordAuthenticationToken-- principal实际的值UserDetails .successHandler(this::createSuccessJson) //AuthenticationException 包含了 登录失败之后的 异常信息 .failureHandler((request, response, exception) - createFailJson(response, exception) ) .permitAll(); //以上提到的路径都放行 }).authenticationManager(jsonAuthenticationManager()); //注销登录 http.logout(logout - logout .logoutUrl(/logout) //退出登录的时候返回用户信息 .logoutSuccessHandler((r, response, a) - createSuccessJson(response, 退出登录成功)) .permitAll() ); //未登录异常提示 http.exceptionHandling().authenticationEntryPoint((request, response, e) - createFailJson(response, 当前用户未登录请先登录再访问)); return http.build(); }四、权限标识授权1、新建数据库CREATE TABLE admin_user_author ( aid int NOT NULL AUTO_INCREMENT, name varchar(255) DEFAULT NULL, code varchar(255) DEFAULT NULL, PRIMARY KEY (aid) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci;关系表CREATE TABLE rel_admin_user_author ( aid int NOT NULL, uid int NOT NULL, PRIMARY KEY (aid,uid) USING BTREE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci;2、添加模拟数据INSERT INTO qingqing.admin_user_author (name, code) VALUES (图书, book); INSERT INTO qingqing.admin_user_author (name, code) VALUES (游戏, game); INSERT INTO qingqing.admin_user_author (name, code) VALUES (音乐, music);关系表INSERT INTO qingqing.rel_admin_user_author (aid, uid) VALUES (1, 1004); INSERT INTO qingqing.rel_admin_user_author (aid, uid) VALUES (2, 1004); INSERT INTO qingqing.rel_admin_user_author (aid, uid) VALUES (3, 1004); INSERT INTO qingqing.rel_admin_user_author (aid, uid) VALUES (1, 1008); INSERT INTO qingqing.rel_admin_user_author (aid, uid) VALUES (2, 1010);3、生成代码TableField(exist false) private ListAdminUserAuthor authorList;4、登录的时候查询授权码列表Override public AdminUser getByUsername(String username) { LambdaQueryWrapperAdminUser queryWrapper new LambdaQueryWrapper(); queryWrapper.eq(AdminUser::getUsername,username); AdminUser adminUser getOne(queryWrapper); if (adminUser ! null){ AdminRole role roleService.getByRid(adminUser.getRoleId().intValue()); adminUser.setAdminRole(role); //授权码 ListAdminUserAuthor authorList authorService.getListByUid(adminUser.getUid()); adminUser.setAuthorList(authorList); } return adminUser; }Service(adminUserAuthorService) public class AdminUserAuthorServiceImpl extends ServiceImplAdminUserAuthorDao, AdminUserAuthor implements AdminUserAuthorService { Resource AdminUserAuthorDao authorDao; Override public ListAdminUserAuthor getListByUid(Integer uid) { return authorDao.selectListByUid(uid); } }daopublic interface AdminUserAuthorDao extends BaseMapperAdminUserAuthor { Select(select a.* from admin_user_author a ,rel_admin_user_author rel where a.aid rel.aid and rel.uid #{uid} ) ListAdminUserAuthor selectListByUid(Integer uid); }5、修改LoginUserDetailsOverride public Collection? extends GrantedAuthority getAuthorities() { ListGrantedAuthority list new ArrayList(); //根据角色授权 AdminRole adminRole adminUser.getAdminRole(); if (adminRole ! null){ GrantedAuthority authority new SimpleGrantedAuthority(ROLE_ adminRole.getCode()); list.add(authority); } //授权码列表 ListAdminUserAuthor authorList adminUser.getAuthorList(); if (authorList ! null !authorList.isEmpty()){ authorList.forEach(a -{ list.add(new SimpleGrantedAuthority(a.getCode())); }); } //存储授权列表 return list; }6、设计测试book能访问f4game能访问f5book,game,music 都能访问f6http.authorizeHttpRequests(auth - auth .requestMatchers(/game/f4).hasAuthority(book) .requestMatchers(/game/f5).hasAuthority(game) .requestMatchers(/game/f6).hasAnyAuthority(book,game,music) .requestMatchers(/loginpage.html, /login/**, /jsonlogin, /phoneLogin) .permitAll() .anyRequest() .authenticated() //其他页面要登录之后才能访问 );7、修改403返回jsonhttp.exceptionHandling(ex - ex //处理 401 未登录/未认证 用户访问未携带cookie/未通过登录 .authenticationEntryPoint((request, response, e) - { createFailJson(response, 当前用户未登录请先登录再访问); }) //处理 403 已经登录权限不足 .accessDeniedHandler((request, response, e) - { createFailJson(response, 权限不足无法访问); }) );有一些特殊情况下这个请求会优先进入JavasmExceptionAdvice从而不触发上面的 exceptionHandling修改自定义异常//import org.springframework.security.access.AccessDeniedException; //import org.springframework.security.core.AuthenticationException; //单独的声明处理Security产生的异常信息直接向上抛出不返回json走Security的异常流程 ExceptionHandler({AccessDeniedException.class, AuthenticationException.class}) public void handleSecurityException(Exception e) throws Exception{ throw e; }五、授权注解如果需要控制的url地址过多需要大量的配置在配置类中需要使用注解来简化配置开启注解//securedEnabled → 开启Secured注解 //prePostEnabled → 开启PreAuthorize/PostAuthorize 注解默认已经开启 //Secured注解 实用性 没有PreAuthorize好所以很大可能用不到 EnableMethodSecurity(securedEnabled true,prePostEnabled true)1、Secured角色的继承会失效GetMapping(/f1) Secured(ROLE_admin) public R f1(){ return R.ok(F1); } Secured(ROLE_test) GetMapping(/f2) public R f2(){ return R.ok(F2); } Secured({ROLE_admin,ROLE_test}) GetMapping(/f3) public R f3(){ return R.ok(F3); }2、PreAuthorize使用比较多方法执行【之前】生效角色继承生效PreAuthorize(hasRole(ROLE_admin)) GetMapping(/f5) public R f5(){ return R.ok(F5); } PreAuthorize(hasRole(ROLE_test)) GetMapping(/f6) public R f6(){ return R.ok(F6); } PreAuthorize(hasAnyRole(ROLE_admin,ROLE_test)) GetMapping(/f7) public R f7(){ return R.ok(F7); }PreAuthorize(hasAuthority(game)) GetMapping(/f8) public R f8(){ return R.ok(F8); } PreAuthorize(hasAuthority(book)) GetMapping(/f9) public R f9(){ return R.ok(F9); } PreAuthorize(hasAnyAuthority(music,book)) GetMapping(/f10) public R f10(){ return R.ok(F10); }3、PostAuthorize方法执行【之后】返回之前生效用法和PreAuthorize一模一样只是生效的时机不一样方法不论是否有权限都会被执行1次但是能不能返回看权限PostAuthorize(hasAnyAuthority(mucic,book)) GetMapping(/f11) public R f11(){ System.out.println(这个日志会被执行不论是否有权限); return R.ok(F11); }4、PreFilter过滤参数参数必须是集合才能生效PreFilter(filterObject.ishot 1) GetMapping(/f13) public ListGame f13(RequestBody ListGame list){ return list; }5、PostFilter过滤返回值返回值必须是集合才能过滤GetMapping(/f12) PostFilter(filterObject.sort 5) public ListGame f12(){ ListGame list gameService.list(); return list; }六、自定义的方法去校验授权1、测试基本原理写一个自己的方法让授权成功也能像role或者Authority那样控制方法能否访问Component(auth1) public class JavasmAuthorize { public boolean test(String code){ System.out.println(code); //test方法返回的数据如果是true表示允许访问当前的方法 //如果返回false表示没有权限访问当前方法 return false; } }使用GetMapping(/f14) //寻找名字是auth1的bean对象调用里面的.test方法传入参数ttttt PreAuthorize(auth1.test(ttttt)) public R f14(){ return R.ok(-----------f14); }2、官方验证Component(auth2) public class JavasmAuthorize2 { //code 权限标识 public boolean f1(String code) { //获取登录用户信息 Object principal SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof LoginUserDetails) { LoginUserDetails loginUserDetails (LoginUserDetails) principal; //获取授权列表 Collection? extends GrantedAuthority authorities loginUserDetails.getAuthorities(); //判断 code 是否在授权列表中 return authorities .stream() .anyMatch(grantedAuthority - grantedAuthority.getAuthority().equals(code) ); } return false; } }使用PreAuthorize(auth2.f1(book)) GetMapping(/f15) public R f15(){ return R.ok(-----------f15); }3、使用自己的方法Component(auth3) public class JavasmAuthorize3 { Resource LoginService loginService; public boolean f1(String code){ LoginUserDetails loginUser loginService.getLoginUser(); //授权列表 ListAdminUserAuthor authorList loginUser.getAdminUser().getAuthorList(); ListString list authorList.stream().map(AdminUserAuthor::getCode).toList(); return list.contains(code); } }使用PreAuthorize(auth3.f1(book)) GetMapping(/f16) public R f16(){ return R.ok(-----------f16); }4、菜单授权授权判定Component(menuAuth) public class MenuAuthorize { public boolean check(String url){ Object principal SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal instanceof LoginUserDetails){ LoginUserDetails loginUserDetails (LoginUserDetails) principal; return loginUserDetails.checkMenu(url); } return false; } }修改LoginUserDetailspublic boolean checkMenu(String url) { if (adminUser ! null adminUser.getAdminRole() ! null) { //获取菜单列表 ListAdminMenu menuList adminUser.getAdminRole().getMenuList(); //获取子菜单的Stream流 StreamString childUrlStream menuList.stream() .map(AdminMenu::getChildList) .flatMap(Collection::stream) .map(AdminMenu::getUrl); //获取父菜单的Stream流 StreamString firstUrlStream menuList.stream().map(AdminMenu::getUrl); //两个流混到一起再筛选出url地址 ListString urlList Stream.concat(childUrlStream, firstUrlStream).toList(); return urlList.contains(url); } return false; }使用PreAuthorize(menuAuth.check(/user/list)) GetMapping(/f17) public R f17(){ return R.ok(-----------f17); }总结PreAuthorize菜单授权
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

外贸 网站 源码宿迁做网站大公司

跨平台C#代码实验神器:RoslynPad终极指南 【免费下载链接】roslynpad 项目地址: https://gitcode.com/gh_mirrors/ros/roslynpad RoslynPad是一款革命性的跨平台C#代码实验工具,基于微软Roslyn编译器和AvalonEdit编辑器构建,为开发者…

张小明 2025/12/25 18:06:11 网站建设

滁州做网站hi444建成网站的关键是

专业化解释 阐述了分类与回归在机器学习中的核心区别、内在联系及本质共性,内容基于监督学习任务的框架:基本区别 输出类型:分类预测离散类别标签(如“男/女”“是/否”),回归预测连续数值(如房…

张小明 2025/12/25 18:06:11 网站建设

有没有做网站的软件找哪些公司做网站

Python Socket编程:深入解析与实践 1. 协程与线程服务器响应时间对比 在某些测试环境下,基于协程的服务器平均响应时间表现优于基于线程的服务器。例如,在一台双核2 GHz的MacBook上,对1000个请求进行测量,基于协程的服务器平均响应时间约为1ms,而基于线程的服务器则为5…

张小明 2025/12/25 15:10:19 网站建设

网站开发所要达到的目标房屋装修设计app

终极U盘量产工具:Chipsbank APTool V7200快速修复与批量生产完整指南 【免费下载链接】ChipsbankAPTool量产工具V72002020-00-21 Chipsbank APTool量产工具是专门针对Chipsbank生产的USB控制芯片设计的一款强大工具。本版本V7200发布于2020年2月21日,针对…

张小明 2025/12/25 18:06:15 网站建设

湖南做网站kaodezhu网络有限公司做女装网站的

MusicFree插件终极指南:3分钟解锁免费音乐新世界 【免费下载链接】MusicFreePlugins MusicFree播放插件 项目地址: https://gitcode.com/gh_mirrors/mu/MusicFreePlugins MusicFree播放器作为开源音乐播放器的代表,其强大的插件系统让用户能够免费…

张小明 2025/12/27 14:32:29 网站建设

网站图片用什么做的如何在云主机上建设网站

BetterNCM安装器完整指南:网易云插件一键管理终极方案 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 厌倦了复杂的插件安装流程?BetterNCM安装器让这一切变得简…

张小明 2025/12/28 11:29:39 网站建设