项目结构
编辑
Security配置类
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true)// 开启鉴权配置注解 public class SecurityConfig extends WebSecurityConfigurerAdapter { //解决跨域 CorsConfigurationSource configurationSource() { List list=new ArrayList(); list.add("http://127.0.0.1:80/"); list.add("http://127.0.0.1:81/"); list.add("http://127.0.0.1:82/"); list.add("http://127.0.0.1:83/"); list.add("http://127.0.0.1:84/"); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.setAllowedHeaders(Collections.singletonList("*")); //允许跨域访问的请求方式Arrays.asList("GET","POST") corsConfiguration.setAllowedMethods(Collections.singletonList("*")); //允许跨域访问的站点Arrays.asList("http://127.0.0.1:5173/")Collections.singletonList("*") corsConfiguration.setAllowedOrigins(list); // 允许携带凭证 corsConfiguration.setAllowCredentials(true); corsConfiguration.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); //对所有URL生效 source.registerCorsConfiguration("/**", corsConfiguration); return source; } @Override protected void configure(HttpSecurity http) throws Exception { // 自定义表单登录 http.formLogin() .usernameParameter("username") // 用户名项 .passwordParameter("password") // 密码项 .loginProcessingUrl("/admin/login") // 登录提交路径 .successHandler(new MyLoginSuccessHandler()) // 登录成功处理器 .failureHandler(new MyLoginFailureHandler()) // 登录失败处理器 // 跨域配置 .and() .cors() .configurationSource(configurationSource()); // 权限拦截配置 http.authorizeRequests() //.antMatchers("/login").permitAll() // 登录页不需要认证 .antMatchers("/admin/login").permitAll() // 登录请求不需要认证 .antMatchers("/file/*").permitAll() .anyRequest().authenticated(); // 其余请求都需要认证 // 退出登录配置 http.logout() .logoutUrl("/admin/logout") // 注销的路径 .logoutSuccessHandler(new MyLogoutSuccessHandler()) // 登出成功处理器 .clearAuthentication(true) // 清除认证数据 .invalidateHttpSession(true); // 清除session // 异常处理 http.exceptionHandling() .authenticationEntryPoint(new MyAuthenticationEntryPoint()) // 未登录处理器 .accessDeniedHandler(new MyAccessDeniedHandler()); // 权限不足处理器 // 关闭csrf防护,取消跨站请求伪造防护 http.csrf().disable(); // 开启跨域访问 http.cors(); } @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } }
认证授权逻辑
@Service public class MyUserDetailService implements UserDetailsService { @DubboReference private AdminService adminService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1.认证 Admin admin = adminService.findByName(username); if(admin == null){ throw new UsernameNotFoundException("用户不存在"); } if (!admin.isStatus()) { throw new UsernameNotFoundException("用户不可用"); } // 2.授权 List<Permission> permissions = adminService.findAllPermission(username); List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); for (Permission permission : permissions) { grantedAuthorities.add(new SimpleGrantedAuthority(permission.getPermissionDesc())); } // 3.封装为UserDetails对象 UserDetails userDetails = User.withUsername(admin.getUsername()) .password(admin.getPassword()) .authorities(grantedAuthorities) .build(); // 4.返回封装好的UserDetails对象 return userDetails; } }
权限不足处理器
/** * 权限不足处理器 */ public class MyAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { response.setContentType("text/json;charset=utf-8"); BaseResult result = new BaseResult(403, "权限不足", null); response.getWriter().write(JSON.toJSONString(result)); } }
未登录处理器
/** * 未登录处理器 */ public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { response.setContentType("text/json;charset=utf-8"); BaseResult result = new BaseResult(401, "用户未登录,请登录", null); response.getWriter().write(JSON.toJSONString(result)); } }
登录失败处理器
/** * 登录失败处理器 */ public class MyLoginFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { response.setContentType("text/json;charset=utf-8"); BaseResult result = new BaseResult(402, "用户名或密码错误", null); response.getWriter().write(JSON.toJSONString(result)); } }
登录成功处理器
/** * 登录成功处理器 */ public class MyLoginSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.setContentType("text/json;charset=utf-8"); UserDetails userDetails = (UserDetails) authentication.getPrincipal(); BaseResult result = new BaseResult(200, "登录成功", userDetails); response.getWriter().write(JSON.toJSONString(result)); } }
登出成功处理器
/** * 登出成功处理器 */ public class MyLogoutSuccessHandler implements LogoutSuccessHandler { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.setContentType("text/json;charset=utf-8"); BaseResult result = new BaseResult(200, "注销成功", null); response.getWriter().write(JSON.toJSONString(result)); } }