Spring Security(一)(基本介绍及使用)

前言

学习security,记录下

正文

1. 简介

Spring Security是为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了完整的安全性解决方案,可以在Web请求级别和方法调用级别处理身份认证和授权充分利用了Spring IOC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能。

2. 模块
  • ACL 支持通过访问控制列表(access control list,ACl)为域对象提供安全性
  • Aspects 一个很小的模块,当使用Spring Security注解时,会使用基于AspectJ的切面
  • CAS Client 提供与CAS集成的功能
  • Configuration 包含XML和JAVA配置的功能支持
  • Core 基本功能库
  • Cryptography 提供加密和密码编码相关功能
  • LDAP 基于LDAP认证
  • OpenID 支持使用OpenID进行集中式认证
  • Remoting 提供了对Spring Remoting的支持
  • Tag Library Security的JSP标签库
  • Web 提供了Security基于Filter的Wen安全性支持
    备注:
    应用程序的类路径下至少需要包括Core和Configuration模块,Web应用下需要加入Web应用
3. Demo(基于SpringBoot+SpringSecurity+MySql)
3.1. pom.xml
    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
            mysql
            mysql-connector-java
        

        
            org.springframework.boot
            spring-boot-starter-data-jpa
        

        
            org.projectlombok
            lombok
        

        
            org.springframework.boot
            spring-boot-starter-freemarker
        

        
            org.springframework.boot
            spring-boot-starter-security
        


        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        

        
            org.thymeleaf.extras
            thymeleaf-extras-springsecurity4
        
        
        
            org.springframework.boot
            spring-boot-devtools
            true
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    true
                    true
                
            
        
    
3.2. config

配置类WebSecurityConfig继承WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity//启用安全
@EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled = true)//开启注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}

重载configure(HttpSecurity)方法,通过重载,配置如何通过拦截器保护请求

@Override
protected void configure(HttpSecurity http) throws Exception {
             http.formLogin().loginPage("/login").loginProcessingUrl("/auth/login").defaultSuccessUrl("/index")//指定登录页面以及登录成功后的跳转页面
                .and()
                .logout().logoutSuccessUrl("/login")//指定登出后的页面
                .and()
                .authorizeRequests()//拦截请求配置
                .antMatchers("/css/**", "/js/**","/images/**", "/static/**").permitAll()//允许访问静态资源
                .antMatchers("/login","/auth/login").permitAll()  //  premitAll()不做拦截
                .antMatchers("/index").authenticated()   //authenticated()  必须登录后可见
                .antMatchers("/hello").access("hasRole('ADMIN')") //必须拥有ADMIN角色权限才可以访问
                .anyRequest().authenticated();
                //.and()
//              .rememberMe().tokenValiditySeconds(2419200).tokenRepository(persistentTokenRepository()).alwaysRemember(true);// 启用记住我
    }

重载configure(AuthenticationManagerBuilder)方法,通过重载,配置user-detail服务
重载configure(WebSecurity)方法,通过重载,配置Security的Filter链

3.3. 四种用户验证方式

上面提到了重载configure(AuthenticationManagerBuilder)方法,可以配置user-detail服务,这个方法决定用户的校验方式,一般来说有四种

  • 基于内存验证
auth.inMemoryAuthentication()
                  .withUser("admin").password(passwordEncoder().encode("admin")).roles("ADMIN").and()
                      .withUser("test").password(passwordEncoder().encode("test")).roles("TEST");
  • 基于数据库验证
auth.jdbcAuthentication().dataSource(dataSource)
              .usersByUsernameQuery("select username,password,enabled from user where username = ?")
              .authoritiesByUsernameQuery("select username,rolename from role where username=?")
              .passwordEncoder(passwordEncoder());
  • 基于LDAP验证
auth.ldapAuthentication().userSearchFilter("{uid=0}").groupSearchFilter("member={0}");
  • 自定义用户服务
auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());

这里customUserDetailsService必须实现UserDetailsService

@Component
@Slf4j
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByAccount(username);
        if (user==null){
            throw new AuthenticationCredentialsNotFoundException("authError");
        }
        Set roles = user.getRoles();
        List authorities = new ArrayList<>();
        roles.forEach(role-> authorities.addAll(AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_"+role.getName())));
        return new org.springframework.security.core.userdetails.User(user.getAccount(),user.getPassword(),authorities);
    }
}
3.4. 注解

三种不同的安全注解

  • 自带的@Secured注解(@EnableGlobalMethodSecurity中设置securedEnabled = true)
  • JSR-250的@RolesAllowed注解(@EnableGlobalMethodSecurity中设置jsr250Enabled = true)
  • 表达式驱动注解,@PreAuthorize、@PostAuthorize、@PreFilter、@PostFilter
    这里我们主要讲表达式驱动注解:
    @PreAuthorize 方法调用之前,基于表达式的计算结果来限制对方法的访问
    @PostAuthorize 方法调用之后,如果表达式的结果为false,则抛出异常
    @PreFilter 方法调用之前,过滤进入方法的输入值
    @PostFilter 方法调用之后,过滤方法的结果值
@Controller
@RequestMapping("/")
public class AuthController {

    @GetMapping("login")
    public String login (){
        return "login";
    }
    @GetMapping("index")
    public String index(){
        return "index";
    }
    @GetMapping("hello")
    @PreAuthorize("hasRole('ADMIN')")
    public String hello(){//必须拥有ADMIN权限的用户才可以进去
        return "hello";
    }
    @GetMapping("postAuth")
    @PostAuthorize("hasRole('TEST')")
    @ResponseBody
    public String  postAuth(){//可以进入但是没有TEST的权限的用户会报403错误
        return "postAuth";
    }
    @PostMapping("preFilter")
    @PreFilter(filterTarget="users", value="filterObject.id != null")
    @ResponseBody
    public String  preFilter(@RequestBody List users){//进入方法后users的size为0
        return "preFilter";
    }
    @PostMapping("postFilter")
    @PostFilter(value="filterObject.id != null")
    @ResponseBody
    public List postFilter(@RequestBody User user){//客户端拿到的是空的
        List users = new ArrayList();
        users.add(user);
        return users;
    }
}

总结

一些基本的功能以及介绍已经了解了,具体的使用还是需要投入到实际项目中,下面接着往下学习。
security是如何进行登录验证和权限控制的?

参考资料
  • Spring In Action 第四版 9章和14章
  • Security 官方文档
  • Security 参考手册
参考代码

demo 地址

你可能感兴趣的:(Spring Security(一)(基本介绍及使用))