Spring Security

1.安全框架的重要性

在我们开发的系统上线后,会面临着来自外界的各种攻击;例如XSS攻击、CSRF攻击等。那么为了让我们的系统正常工作;我们需要引用安全框架来维持我们系统的正常运行。

2. Spring Security的介绍

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

3. 安全框架的选择

在Java体系中,为我们的软件提供安全有多种实现方式。例如自己实现过滤器、拦截器;前面这两种方式,如果想让我们的程序更加安全,那么就需要我们写过多的过滤器或者拦截器;当然我们还可以选择框架性,比较出名的有Apache旗下的Shiro框架,Spring的子项目Spring Security;Shiro 更适合于单体项目;由于我们的系统是分布式的;所以我们选择的Spring Security。

4 Spring Security的原理

Spring Security的实现是通过一组过滤器链完成的。为了能够更深入的了解Spring Security。我们有必要知道核心过滤器是如何工作的。(图1-1)
Spring Security运行流程
Spring Security支持多种认证模式:
HTTP BASIC 认证头 (基于 IETF RFC-based 标准)
HTTP Digest 认证头 ( IETF RFC-based 标准)
HTTP X.509 客户端证书交换 ( IETF RFC-based 标准)
LDAP (一个非常常见的方法来跨平台认证需要, 尤其是在大型环境)
Form-based authentication (用于简单的用户界面)
OpenID 认证等
在这里为了方便我们的学习,模拟HTTP来请求我们的接口资源。采用表单认证模式,对上图(图1-1)中重要的过滤器打断掉调试,并列出了详细的步骤。
1)当用户要访问我们的接口资源时,会先通过AbstractAuthenticationProcessingFilter过滤器,该过滤器会判断访问的接口是否需要认证,
2)如果需要认证,由于我们采用的是表单认证模式,所以来到下一个过滤器UsernamePasswordAuthenticationFilter,这个过滤器会获取用户名密码,并进行非空校验,根据用户名,密码 创建 UsernamePasswordAuthenticationToken对象,调用AuthenticationManager接口authenticate方法,并将UsernamePasswordAuthenticationToken作为参数
3)AuthenticationManager接口的默认实现类是ProviderManager,ProviderManager不直接自己处理认证请求,而是委托给其所配置的 AuthenticationProvider 列表,会一直调用AuthenticationProvider 进行认证,直到列表里面的AuthenticationProvider认证完,如果当中有一个认证成功,后面的AuthenticationProvider将不会继续往后认证。如果所有的AuthenticationProvider的认证结果都为 null,则表示认证失败,将抛出一个 ProviderNotFoundException。
4)然后来到ExceptionTranslationFilter,这时一个捕获异常的过滤器
5)最后来到FilterSecurityInterceptor,该过滤器最后决定是否允许访问我们的资源。

5. Spring Security实战

环境:jdk1.8 ,idea 2018.2.4,maven 3.3.9
框架版本:spring boot 1.5.7, Spring Security 4.2.3
引入依赖:

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
       </dependency>

Spring Security给我们提供了 org.springframework.security.core.userdetails.UserDetailsService
我们只需要继承该接口,重写 loadUserByUsername方法,我们就可以设置一些用户相关的信息。例如我自已继承了 UserDetailsService并重重写了 loadUserByUsername,从数据库中获取用户信息,最后返回 org.springframework.security.core.userdetails.User 对象。

@Service
@Slf4j
public class UserDetailServiceImpl implements UserDetailsService{

    @Autowired
    private UserMapper userMapper;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        com.huawang.hwbasic.pojo.User  user = userMapper.findByUsername(username);
        System.out.println(user);
        log.info("----------->"+user);
        return new User(username,user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

Spring Security 5.0之前默认是采用Http Basic登录方式,登录接口默认是 /login 并且是POST 请求。当然这些我们都是可以自己定义的。
Spring Security为我们提供了org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter抽象类
我们需要自己继承它并重写 configure(HttpSecurity http) 该configure 一共有三个重载方法,这时注意我们选择的是参数为HttpSecurity 的方法;在方面里面我们通过修改HttpSecurity 的一些属性,来满足我们的需求,如下:
① .formLogin() 选择采用表单登录方式。
② .loginPage("/login.html") 设置自己的登录页面。
③.loginProcessingUrl("/form/login") 设置处理的登录请求
④.successHandler(successHandler) 设置登录成功处理Handle
⑤ .failureHandler(failHalder) 设置登录失败处理Handle
⑥ .antMatchers("/login.html","/form/login").permitAll() 等方式处理要拦截的请求。

@Configuration
public class WebSecurityAdapter extends WebSecurityConfigurerAdapter {

    /**
     * 设置加密方式
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    /**
     * 登陆成功Handler
     */
    @Autowired
    private AuthenticationSuccessHandler successHandler;
    /**
     * 登陆失败Handler
     */
    @Autowired
    private AuthencationFailHalder failHalder;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .formLogin()  //选择采用表单登录方式
                .loginPage("/login.html")  // 自定义login.html为自己的登录页面
                .loginProcessingUrl("/form/login")  // 设置处理的登录请求为 /form/login ,Spring Security默认是 /login    
                .successHandler(successHandler)  // 添加登录成功处理Handle
                .failureHandler(failHalder)      // 添加登录失败处理Handle
                .and()
                .authorizeRequests() 
                .antMatchers("/login.html","/form/login").permitAll()  // /login.html ,/form/login 请求匿名账号允许访问
                .anyRequest() //匹配所有的请求,未登录用户不允许访问
                .authenticated()  
                .and().csrf().disable(); // 关闭csrf,在开发中建议关闭掉


    }

自定义登录处理逻辑,登陆成功后,可以返回前端需要的数据,例如将用户信息返回给前端。Spring Security给我们提供了org.springframework.security.web.authentication.AuthenticationSuccessHandler我们只需要实现它,并定义自己的代码既可以了。

@Component
public class LoginSuccessHalder implements AuthenticationSuccessHandler {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(authentication));
    }
}

同理处理登录失败逻辑,在这里,可以做一些登陆失败校验的提示信息。Spring Security给我们提供了 org.springframework.security.web.authentication.AuthenticationFailureHandler

`@Component
public class AuthencationFailHalder implements AuthenticationFailureHandler {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {

        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(exception));
    }
    }


通过前面讲解Spring Security的运行原理,再来编写一个小demo,就能让我们更加的了解Spring Security

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值