spring security
来源:互联网 发布:js定时器setinterval 编辑:程序博客网 时间:2024/06/05 11:47
本文讲述spring Boot整合Spring Security在方法上使用注解实现权限控制,使用自定义UserDetailService,从MySQL中加载用户信息。使用Security自带的MD5加密,对用户密码进行加密。
spring security 的验证流程:
- 用户发出请求
- 过滤器拦截(OauthAuthenticationFilter:doFilter)
- 取得请求资源所需权限(UserDetailService.loadUserByUsername)
- 匹配用户拥有权限和请求权限(AuthenticationProvider authenticate()),如果用户没有相应的权限,
执行第5步,否则执行第6步。 - 登录
- 验证并授权(MyUserDetailServiceImpl:loadUserByUsername)
1、配置类 Spring Security
- 通过 @EnableWebSecurity 注解开启Spring Security的功能
- 继承 WebSecurityConfigurerAdapter ,并重写它的方法来设置一些web安全的细节
- configure(HttpSecurity http) 方法
- 自定义成功/失败的 handle
@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Resource private FindByIndexNameSessionRepository<ExpiringSession> sessionRepository; @Resource private AdminUserDetailsService adminUserDetailsService; @Resource private DaoAuthenticationProvider daoAuthenticationProvider; @Override protected void configure(HttpSecurity http) throws Exception { SessionManagementConfigurer<HttpSecurity> sessionManagement = http.sessionManagement(); sessionManagement.sessionCreationPolicy(SessionCreationPolicy.ALWAYS); sessionManagement.sessionFixation().migrateSession(); http.csrf().disable(); http.authorizeRequests().antMatchers("/*").permitAll() .requestMatchers(CorsUtils::isPreFlightRequest).permitAll(); http.exceptionHandling().accessDeniedHandler(new JsonAccessDeniedHandler(BaseExceptionEnum.ACCESS_DENIED.getMessage(), BaseExceptionEnum.ACCESS_DENIED.getCode())); http.logout().logoutUrl("/api/adminUser/logout").logoutSuccessHandler(new JsonLogoutSuccessHandler(BaseExceptionEnum.SUCCESS.getMessage(), BaseExceptionEnum.SUCCESS.getCode())); http.formLogin().loginPage("/api/adminUser/login").usernameParameter("phone") .successHandler(new JsonAuthenticationSuccessHandler(BaseExceptionEnum.SUCCESS.getMessage(), BaseExceptionEnum.SUCCESS.getCode())) .failureHandler(new JsonAuthenticationFailureHandler(BaseExceptionEnum.INVALID_ACCOUNT_PASSWORD.getMessage(), BaseExceptionEnum.INVALID_ACCOUNT_PASSWORD.getCode())); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(daoAuthenticationProvider()); } /** * 配置数据库校验逻辑:手机号码+密码 * * @return */ @Bean public DaoAuthenticationProvider daoAuthenticationProvider() { DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); // 设置用户查询处理逻辑的类 daoAuthenticationProvider.setUserDetailsService(adminUserDetailsService); // 设置密码加密的盐值 // ReflectionSaltSource saltSource = new ReflectionSaltSource(); // saltSource.setUserPropertyToUse("username"); // daoAuthenticationProvider.setSaltSource(saltSource); // 设置密码加密算法 ShaPasswordEncoder shaPasswordEncoder = new ShaPasswordEncoder(512); daoAuthenticationProvider.setPasswordEncoder(shaPasswordEncoder); return daoAuthenticationProvider; } @Bean @Autowired public SpringSessionBackedSessionRegistry springSessionBackedSessionRegistry(FindByIndexNameSessionRepository sessionRepository) { return new SpringSessionBackedSessionRegistry(sessionRepository); }}
2、自定义 UserDetailService
- 检索使用自己选择的持久化策略的认证信息
- 在 loadUserByUsername() 获取数据库用户信息,并添加相应的权限到 UserDetails
@Servicepublic class AdminUserDetailsService implements UserDetailsService { @Resource private AdminUserMapper adminUserMapper; @Resource private CustomAdminUserMapper customAdminUserMapper; @Resource private AdminManagementService adminManagementService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { AdminUserExample example = new AdminUserExample(); example.createCriteria().andPhoneEqualTo(username); List<AdminUser> list = adminUserMapper.selectByExampleWithBLOBs(example); if (list == null || list.size() == 0) { throw new JrdException(JrdExceptionEnum.ADMIN_NOT_FOUND); } AdminUser adminUser = list.get(0); Set<GrantedAuthority> adminAuthorities = adminManagementService.getAdminAuthorities(adminUser); Boolean accountNonLocked = true; if (adminUser.getUserStatus() != null) accountNonLocked = UserStatusEnum.isUserAccountEnabled(adminUser.getUserStatus()); if (adminUser == null) { throw new UsernameNotFoundException(AdminUserExceptionEnum.ADMIN_USER_NOT_FOUND.getMessage()); } return new AdminUserDetails(adminUser,adminAuthorities); }}
3、用声明式注解 @PreAuthorize 修饰 Controller 方法
这里有两种用法:
- @PreAuthorize(“hasAuthority(‘authorized’,’ROLE_XXX)”)
- @PreAuthorize(“hasPermission(‘authorized’, ”)”)
例如: @RequestMapping(value = "/saveAccount", method = RequestMethod.POST) @PreAuthorize("hasPermission('authorized', '')") public String saveAccount(@Validated(Save.class) User user) { logger.info(user.getUsername() + " " + user.getCompanyName()); userService.saveUser(user); return ApiJsonSerializeUtil.jsonResponse(user); }
第一种 hasAuthority : spring security 会从 UserDetail 里面 getAuthorities() 里拿出该用户对应的权限,然后再自动帮我们校验;
第二种 hasPermission : 需要配置PermissionEvaluator 、GlobalMethodSecurityConfiguration 两个类。在 PermissionEvaluator 中的 hasPrivilege() 方法中进行权限校验。
@Componentpublic class AdminPermissionEvaluator implements PermissionEvaluator { public static final String AUTHORIZED = "AUTHORIZED"; // 要求登录 @Override public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { if (authentication == null || !(permission instanceof String)) { return false; } return hasPrivilege(authentication, targetDomainObject.toString(), permission.toString().toUpperCase()); } @Override public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { return hasPermission(authentication, null, permission); } private Boolean hasPrivilege(Authentication authentication, String targetType, String permission) { if (authentication instanceof AnonymousAuthenticationToken) { return false; } AdminUserDetails principal = (AdminUserDetails) authentication.getPrincipal(); Set<GrantedAuthority> authorities = (Set<GrantedAuthority>) principal.getAuthorities(); if (!permission.equals("")){ for (GrantedAuthority authoritie : authorities){ if (authoritie.getAuthority().equals(permission)){ return true; } } return false; } if (authentication.getPrincipal() != null && authentication.getPrincipal() instanceof AdminUserDetails) { return true; } else { return false; } }}
@Configuration@EnableGlobalMethodSecurity(prePostEnabled = true)public class AdminSecurityMethodConfig extends GlobalMethodSecurityConfiguration { @Resource private AdminPermissionEvaluator adminPermissionEvaluator; @Override protected MethodSecurityExpressionHandler createExpressionHandler() { DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler(); expressionHandler.setPermissionEvaluator(adminPermissionEvaluator); return expressionHandler; }}
阅读全文
0 0
- Spring Security
- Spring Security
- spring security
- spring security
- spring security
- spring security
- spring security
- spring security
- spring security
- spring security
- spring security
- Spring Security
- spring security
- spring-security
- Spring Security
- Spring Security
- spring security
- spring Security
- python︱处理与使用json格式的数据(json/UltraJSON/Demjson)
- jsvascript在HTML中的引入方式整理
- Java 22:Spring 5(Spring MVC 入门)
- css布局——双飞翼布局和圣杯布局
- 【NOIP2017提高A组模拟8.23】密码
- spring security
- NoSQL数据库入门概述
- opencv-python安装(解决出现DLL Load failed的问题)
- solr 从数据库导入数据,全量索引和增量索引
- Vue+Node+MongoDB从开发到正式部署
- Windows7下VS2008试用版到期的解决办法
- C# 并行编程 之 并发集合 (.Net Framework 4.0)
- Java中Date各种相关用法
- hdu 6155