在背景管理系統中,通常需要存取權限控制,以限制不同使用者對介面的存取能力。如果使用者缺乏特定權限,則無法存取某些介面。
本文將用 waynboot-mall 專案舉例,為大家介紹常見後管系統如何引入權限控制框架 Spring Security。大綱如下:
waynboot-mall 專案網址:https://github.com/wayn111/waynboot-mall
Spring Security 是一個基於 Spring 框架的開源項目,旨在為 Java 應用程式提供強大且靈活的安全解決方案。 Spring Security 提供了以下特性:
在 waynboot-mall 專案中直接引入 spring-boot-starter-security 依賴,
org.springframework.boot spring-boot-starter-security 3.1.0
在 Spring Security 3.0 中要設定 Spring Security 跟以往是有些不同的,例如不在繼承 WebSecurityConfigurerAdapter。在 waynboot-mall 專案中,具體配置如下,
@Configuration @EnableWebSecurity @AllArgsConstructor @EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true) public class SecurityConfig { private UserDetailsServiceImpl userDetailsService; private AuthenticationEntryPointImpl unauthorizedHandler; private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; private LogoutSuccessHandlerImpl logoutSuccessHandler; @Bean public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { httpSecurity // cors启用 .cors(httpSecurityCorsConfigurer -> {}) .csrf(AbstractHttpConfigurer::disable) .sessionManagement(httpSecuritySessionManagementConfigurer -> { httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS); }) .exceptionHandling(httpSecurityExceptionHandlingConfigurer -> { httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint(unauthorizedHandler); }) // 过滤请求 .authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> { authorizationManagerRequestMatcherRegistry .requestMatchers("/favicon.ico", "/login", "/favicon.ico", "/actuator/**").anonymous() .requestMatchers("/slider/**").anonymous() .requestMatchers("/captcha/**").anonymous() .requestMatchers("/upload/**").anonymous() .requestMatchers("/common/download**").anonymous() .requestMatchers("/doc.html").anonymous() .requestMatchers("/swagger-ui/**").anonymous() .requestMatchers("/swagger-resources/**").anonymous() .requestMatchers("/webjars/**").anonymous() .requestMatchers("/*/api-docs").anonymous() .requestMatchers("/druid/**").anonymous() .requestMatchers("/elastic/**").anonymous() .requestMatchers("/message/**").anonymous() .requestMatchers("/ws/**").anonymous() // 除上面外的所有请求全部需要鉴权认证 .anyRequest().authenticated(); }) .headers(httpSecurityHeadersConfigurer -> { httpSecurityHeadersConfigurer.frameOptions(HeadersConfigurer.FrameOptionsConfig::disable); }); // 处理跨域请求中的Preflight请求(cors),设置corsConfigurationSource后无需使用 // .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() // 对于登录login 验证码captchaImage 允许匿名访问 httpSecurity.logout(httpSecurityLogoutConfigurer -> { httpSecurityLogoutConfigurer.logoutUrl("/logout"); httpSecurityLogoutConfigurer.logoutSuccessHandler(logoutSuccessHandler); }); // 添加JWT filter httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); // 认证用户时用户信息加载配置,注入springAuthUserService httpSecurity.userDetailsService(userDetailsService); return httpSecurity.build(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception { return authenticationConfiguration.getAuthenticationManager(); } /** * 强散列哈希加密实现 */ @Bean public BCryptPasswordEncoder bCryptPasswordEncoder() { return new BCryptPasswordEncoder(); } }
這裡詳細介紹下 SecurityConfig 設定類別:
要使用 Spring Security,只需要在需要控制存取權的方法或類別上新增對應的 @PreAuthorize 註解即可,如下,
@Slf4j @RestController @AllArgsConstructor @RequestMapping("system/role") public class RoleController extends BaseController { private IRoleService iRoleService; @PreAuthorize("@ss.hasPermi('system:role:list')") @GetMapping("/list") public R list(Role role) { Page page = getPage(); return R.success().add("page", iRoleService.listPage(page, role)); } }
我們在list 方法上加了 @PreAuthorize(“@ss.hasPermi('system:role:list')”) 註解表示目前登入使用者擁有system:role:list 權限才能存取list 方法,否則回傳權限錯誤。
在 SecurityConfig 設定類別中我們定義了 UserDetailsServiceImpl 作為我們的使用者資訊載入的實作類,從而透過讀取資料庫中使用者的帳號、密碼與前端傳入的帳號、密碼進行比對。程式碼如下,
@Slf4j @Service @AllArgsConstructor public class UserDetailsServiceImpl implements UserDetailsService { private IUserService iUserService; private IDeptService iDeptService; private PermissionService permissionService; public static void main(String[] args) { BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); System.out.println(bCryptPasswordEncoder.encode("123456")); } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1. 读取数据库中当前用户信息 User user = iUserService.getOne(new QueryWrapper().eq("user_name", username)); // 2. 判断该用户是否存在 if (user == null) { log.info("登录用户:{} 不存在.", username); throw new UsernameNotFoundException("登录用户:" + username + " 不存在"); } // 3. 判断是否禁用 if (Objects.equals(UserStatusEnum.DISABLE.getCode(), user.getUserStatus())) { log.info("登录用户:{} 已经被停用.", username); throw new DisabledException("登录用户:" + username + " 不存在"); } user.setDept(iDeptService.getById(user.getDeptId())); // 4. 获取当前用户的角色信息 Set rolePermission = permissionService.getRolePermission(user); // 5. 根据角色获取权限信息 Set menuPermission = permissionService.getMenuPermission(rolePermission); return new LoginUserDetail(user, menuPermission); } }
針對 UserDetailsServiceImpl 的程式碼邏輯進行一個講解,大家可以配合程式碼理解。
本文告訴大家來說明了後管系統如何引入權限控制框架 Spring Security 3.0 版本以及程式碼實戰。相信能幫助大家對權限控制框架 Spring Security 有一個清晰的理解。後續大家可以按照本文的使用指南一步一步將 Spring Security 引入的自己的專案中用於存取權限控制。
以上是Spring Security權限控制框架使用指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!