Spring Security 应用实践

概述

Spring Security 是 Spring 在安全方面的推出的框架,是采用责任链的设计模式,基于 Spring AOP 和 Servlet 过滤器进行实现。这篇文章记录认证授权的一些概念,以及如何使用其进行扩展保护我们的应用。

认证与授权的概念

  • 认证:我是谁
  • 授权:有哪些访问权限

在系统安全方面,我们面临的两个问题是:

1、如何保护需要访问权限的资源?

在 Java 中我们一般使用过滤器对我们的资源进行保护,使用拦截器对方法的访问进行控制。

2、用户的登录状态要如何传递?

如何让服务器意识到用户已经登录过系统了?一种是使用 Session 进行认证,令一种是使用 Token (令牌) 进行认证。

Session 认证

这种认证方式的缺点是:一是不能用于移动端的认证,二是一旦客户禁用浏览器 Cookie 将会导致无法认证。以下是基于 Session 认证的流程:

用户密码登录 --> 服务器验证通过,为用户创建一个Session(服务器中的一小块内存区域),存储登录用户信息 
--> 返回 SessionID,写入用户Cookie --> Cookie将与每个后续请求一起发送 --> 将SessionID与服务器中的信息进行比对
Token 认证
  • 自定义 Token

我们可以在用户认证成功后生成自定义令牌,保存在Redis或者内存中,返回给前端,用户后续的每次请求都在在请求头 Authorization 中携带令牌,而不是将认证信息存放在请求头 Cookie 中。之后我们将请求头中的令牌与服务器存储的令牌进行比较,验证用户的登录状态。

  • JWT(JSON Web Tokens)

另外一种方案是使用 JWT。
优点:1、无需对Token进行存储,可以直接通过计算进行校验,以时间换空间。2、可以在 Token 中存储用户的相关信息
缺点:Token 无法随时废弃。

Spring Security 配置

Spring Security 是一款高度可配置化的框架,我们可以继承或者实现相关的类,从而实现定制化功能。以下是配置的一个示例:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private final AuthSuccessHandler authSuccessHandler;

    private final AuthFailureHandler authFailureHandler;

    private final SimpleAccessDeniedHandler accessDeniedHandler;

    private final SimpleAuthenticationEntryPoint authenticationEntryPoint;

    private final JwtProperties jwtProperties;

    /**
     * 配置不需要进行认证的接口
     */
    @Override
    public void configure(WebSecurity web) {
        web.ignoring()
                .antMatchers(HttpMethod.OPTIONS, "/**")
                .antMatchers("/css/**")
                .antMatchers("/signUp.html")
                .antMatchers("/user/**")
                .antMatchers("/common/test")
                .antMatchers("/test");
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/login")
                .successHandler(authSuccessHandler)
                .failureHandler(authFailureHandler)
                .permitAll()
                .and()
                .headers()
                .frameOptions()
                .disable()
                .and()
                .authorizeRequests()
                .antMatchers("/login.html").permitAll()
                //开启认证
                .anyRequest().authenticated()
                .and().csrf().disable()
                //前后端分离采用JWT 不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                //添加自定义权限过滤器
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler)
                .and()
                .addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtProperties.getSecretKey()));
    }
}

简单总结下,通过上面的代码,可以看出,我们可以做以下的一些配置:
1、配置不需要进行认证的路径
2、添加过滤器,可以自定义 Token 认证逻辑,主要是通过继承:BasicAuthenticationFilter,重写认证方法
3、自定义一些处理器:

  • 认证成功处理器:在认证成功后需要什么后续的处理?比如:向前端返回JSON 数据,主要通过实现 AuthenticationSuccessHandler 接口
  • 认证失败处理器:认证失败该做什么处理?如:返回自定义认证失败信息,在前后端分离的情况下,可以返回认证失败的 JSON 数据给前端,主要通过实现 AuthenticationFailureHandler 接口

4、访问需要权限的资源,未授权时要怎么对异常进行处理?可以抛出一些更家友好的提示等:主要实现:AuthenticationEntryPoint 接口
5、权限不足异常处理,如:前后端分离情况下,可以自定义返回 JSON 数据,主要通过实现:SimpleAccessDeniedHandler 接口
6、从哪里获取用户信息?我们可以实现:UserDetailsService 接口,实现 loadUserByUsername 方法,让程序从数据库当中获取我们的数据。

最后

所涉及的代码可以点击这里

参考链接

个人博客:https://www.kangpeiqin.cn/#/index
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值