A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 hydee 于 2018-5-23 19:00 编辑

1.Spring Security的认证规则
要编写自定义的认证规则,首先需要对Spring Security中的认证规则有一定的了解,下面简单介绍下Spring Security的认证规则。

1)在Spring Security中每个URL都是一个资源,当系统启动的时候,Spring Security会根据配置将所有的URL与访问这个URL所需要的权限的映射数据加载到Spring Security中。
2)当一个请求访问一个资源时,Spring Security会判断这个URL是否需要权限验证,如果不需要,那么直接访问即可。
3)如果这个URL需要进行权限验证,那么Spring Security会检查当前请求来源所属用户是否登录,如果没有登录,则跳转到登录页面,进行登录操作,并加载这个用户的相关信息
4)如果登录,那么判断这个用户所拥有的权限是否包含访问这个URL所需要的权限,如果有则允许访问,否则不予放行。
2.自定义认证和权限判断实现
2.1自定义UserDetailsService
@Component
public class CustomUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LogManager.getLogger("CustomUserDetailsService").info("loadUserByUsername invoke");
        // 提供到数据库查询该用户的权限信息
        // 关于角色和权限的转换关系在此处处理,根据用户与角色的关系、角色与权限的关系,
        // 此处伪造一些数据
        // 伪造权限
        AuthorityModel authority = new AuthorityModel("AUTH_WELCOME");
        List<AuthorityModel> authorities = new ArrayList<>();
        authorities.add(authority);
        
        AccountInfoModel account = new AccountInfoModel("oolong", "12345");
        account.setAuthorities(authorities);
        return account;
    }
}
2.2自定义AuthenticationProvider
@Componentpublic class CustomUserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
    @Autowired
    private UserDetailsService userDetailsService;
   
    public UserDetailsService getUserDetailService() {
        return this.userDetailsService;
    }
    public void setUserDetailService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }
    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        
    }
    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        LogManager.getLogger("CustomUserDetailsAuthenticationProvider").info("retrieveUser invoke");
        
        if (userDetailsService == null) {
            throw new AuthenticationServiceException("");
        }
        
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        
        if (userDetails == null) {
            throw new UsernameNotFoundException(username);
        }
        
        if (userDetails.getUsername().equals(authentication.getPrincipal().toString())
                && userDetails.getPassword().equals(authentication.getCredentials().toString())) {
            return userDetails;
        }
        
        throw new BadCredentialsException(username + authentication.getCredentials());
    }
}
2.4自定义AccessDecisionManager
@Componentpublic class CustomAccessDecisionManager implements AccessDecisionManager {
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {
        
        LogManager.getLogger("CustomAccessDecisionManager").info("decide invoke");
        
        if (configAttributes == null) {
            return;
        }
        
        if (configAttributes.size() <= 0) {
            return;
        }
        
        Iterator<ConfigAttribute> authorities = configAttributes.iterator();
        String needAuthority = null;
        
        while(authorities.hasNext()) {
            ConfigAttribute authority = authorities.next();
            
            if (authority == null || (needAuthority = authority.getAttribute()) == null) {
                continue;
            }
            LogManager.getLogger("CustomAccessDecisionManager").info("decide == " + needAuthority);
            
            for (GrantedAuthority ga : authentication.getAuthorities()) {
                if (needAuthority.equals(ga.getAuthority().trim())) {
                    return;
                }
            }
        }
        throw new AccessDeniedException("No Authority");
    }
    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }
    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
3.实现组合配置
Spring MVC中,Spring Security是通过过滤器发挥作用的,因此我们就爱那个决策管理器与数据加载放到一个过滤器中,然后将这个过滤器插入到系统的过滤器链中。
@Configuration
@ComponentScan(basePackageClasses={TempHook.class})
@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {
   
    @Autowired
    private CustomUserDetailsAuthenticationProvider customAuthenticationProvider;
   
    @Autowired
    private CustomAccessDecisionManager customAccessDecisionManager;
   
    @Autowired
    private CustomSecurityMetadataSource customSecurityMetadataSource;
   
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(customAuthenticationProvider);
    }
   
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterAfter(customFilterSecurityInterceptor(), ExceptionTranslationFilter.class);
        http.formLogin();
    }
   
    @Bean
    public FilterSecurityInterceptor customFilterSecurityInterceptor() {
        FilterSecurityInterceptor fsi = new FilterSecurityInterceptor();
        fsi.setAccessDecisionManager(customAccessDecisionManager);
        fsi.setSecurityMetadataSource(customSecurityMetadataSource);
        
        return fsi;
    }
}

01_Security结构图.png (19.9 KB, 下载次数: 7)

01_Security结构图.png

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马