Spring Security初识和表单认证(一) - Java技术债务

1. Spring Security简介

Spring Security 的前身是 Acegi Security,在被收纳为Spring子项目后正式更名为Spring Security。

应用程序的安全性通常体现在两个方面:认证和授权。

  • 认证是确认某主体在某系统中是否合法、可用的过程。这里的主体既可以是登录系统的用户,也 可以是接入的设备或者其他系统。
  • 授权是指当主体通过认证之后,是否允许其执行某项操作的过程。

这些概念并非Spring Security独有,而是应用安全的基本关注点。Spring Security可以帮助我们更便 捷地完成认证和授权。

Spring Security 支持广泛的认证技术,这些认证技术大多由第三方或相关标准组织开发。Spring Security 已经集成的认证技术如下:

◎ HTTP BASIC authentication headers:一个基于IETF RFC的标准。

◎ HTTP Digest authentication headers:一个基于IETF RFC的标准。

◎ HTTP X.509 client certificate exchange:一个基于IETF RFC的标准。

◎ LDAP:一种常见的跨平台身份验证方式。

◎ Form-based authentication:用于简单的用户界面需求。

◎ OpenID authentication:一种去中心化的身份认证方式。

◎ Authentication based on pre-established request headers:类似于 Computer Associates SiteMinder,一种用户身份验证及授权的集中式安全基础方案。

◎ Jasig Central Authentication Service:单点登录方案。

◎ Transparent authentication context propagation for Remote Method Invocation(RMI) and HttpInvoker:一个Spring远程调用协议。

◎ Automatic "remember-me" authentication:允许在指定到期时间前自行重新登录系统。

◎ Anonymous authentication:允许匿名用户使用特定的身份安全访问资源。

◎ Run-as authentication:允许在一个会话中变换用户身份的机制。

◎ Java Authentication and Authorization Service:JAAS,Java验证和授权API。

◎ Java EE container authentication:允许系统继续使用容器管理这种身份验证方式。

◎ Kerberos:一种使用对称密钥机制,允许客户端与服务器相互确认身份的认证协议。

除此之外,Spring Security还引入了一些第三方包,用于支持更多的认证技术,如JOSSO等。如果 所有这些技术都无法满足需求,则Spring Security允许我们编写自己的认证技术。因此,在绝大部分情 况下,当我们有Java应用安全方面的需求时,选择Spring Security往往是正确而有效的。

在授权上,Spring Security不仅支持基于URL对Web的请求授权,还支持方法访问授权、对象访问授权等,基本涵盖常见的大部分授权场景。

Spring Security初识和表单认证(一) - Java技术债务

2. 创建项目工程

2.1 修改pom.xml配置文件


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

Spring Security初识和表单认证(一) - Java技术债务

引入security包后,可以看到自动引入spring-security-web和spring- security -config、spring- security -aop两个核心模块,这正是官方建议引入的Sp ring Security最小依赖

2.2 添加路由

@GetMapping("/")
@ResponseBody
public String test2() {
    return "hello , Java技术债务!";
}

2.3 启动工程

访问http://127.0.0.1:8705/

Spring Security初识和表单认证(一) - Java技术债务

在引入Spring Security项目之后,虽然没有进行任何相关的配置或编码,但Spring Security有一个默 认的运行状态,要求在经过HTTP基本认证后才能访问对应的URL资源,其默认使用的用户名user, 密码则是动态生成并打印到控制台的一串随机码。翻看控制台的打印信息,可以看到

Spring Security初识和表单认证(一) - Java技术债务

输入用户名和密码后,单击“登录”按钮即可成功访问页面

Spring Security初识和表单认证(一) - Java技术债务

当然,右HTTP基本认证中,用户名和密码都是可以配置的,最常见的就是在resources下的配置文 件中修改。

spring.security.user.name=1
spring.security.user.password=1

重新启动程序,发现控制台不再打印默认密码串了,此时使用我们自定义的用户名和密码即可登录。

事实上,绝大部分Web应用都不会选择HTTP基本认证这种认证方式,除安全性差、无法携带cookie等因素外,灵活性不足也是它的一个主要缺点。通常大家更愿意选择表单认证,自己实现表单登录页和验证逻辑,从而提高安全性。

3. 自定义表单认证

3.1 创建配置文件

WebSecurityConfig.java

package com.cuizb.cloud.alibaba.gtw.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * @author: Java技术债务
 * @Date: 2021/6/5 18:45
 * Describe: SpringSecurity配置
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    public void configure(HttpSecurity http) throws Exception {
        log.info("Using de fault configure(HttpSecurity).If subclassed this will potentially override subclass configure(HttpSecurity) .");
        http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/blog-web/login").permitAll()
                .and()
                .csrf().disable();
    }
}

Spring Security初识和表单认证(一) - Java技术债务

3.2 HttpSecurity

HttpSecurity实际上对应了Spring Security命名空间配置方式中XML文件内的标签,允许我们为特 定的HTTP请求配置安全策略。

HttpSecurity提供了很多配置相关的方法,分别对应命名空间配置中的子标签 。例如authorizeRequests()、formLogin()、httpBasic()和 csrf()分别对应 标签。调用这些方法之后,除非使用and()方法结束当前标签,上下文 才会回到HttpSecurity,否则链式调用的上下文将自动进入对应标签域。

authorizeRequests()方法实际上返回了一个 URL 拦截注册器,我们可以调用它提供的 anyanyRequest()、antMatchers()和regexMatchers()等方法来匹配系统的URL,并为其指定安全 策略。

formLogin()方法和httpBasic()方法都声明了需要Spring Security提供的表单认证方式,分别返 回 对 应 的 配 置 器 。 其 中 , f o r m L o gi n ( ) . l o gi n P a ge ( " / m y L o gi n . h t m l " ) 指 定 自 定 义 的 登 录 页/myLogin.html,同时,Spring Security会用/myLogin.html注册一个POST路由,用于接收登录请求。

csrf()方法是Spring Security提供的跨站请求伪造防护功能,当我们继承 WebSecurityConfigurerAdapter时会默认开启csrf()方法。关于csrf()方法的更多内容会在后面的章节专门探讨,以使测试 进程更加顺利。

3.3 其他表单配置项

package com.cuizb.cloud.alibaba.gtw.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author: Java技术债务
 * @Date: 2021/6/5 18:45
 * Describe: SpringSecurity配置
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    public void configure(HttpSecurity http) throws Exception {
        log.info("Using de fault configure(HttpSecurity).If subclassed this will potentially override subclass configure(HttpSecurity) .");
        http.authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .loginPage("/blog-web/login")
                .loginProcessingUrl("/blog-web/userLogin")
                .successHandler(new UserAuthenticationSuccessHandler())
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
                        response.setStatus(401);
                        PrintWriter writer = response.getWriter();
                        writer.write("fail");
                    }
                })
                .permitAll()
                .and()
                .csrf().disable();
    }
}

表单登录配置模块提供了 successHandler()和 failureHandler()两个方法,分别处理登录成功和 登录失败的逻辑。其中,successHandler()方法带有一个Authentication参数,携带当前登录用户及其角色等信息;而failureHandler()方法携带一个AuthenticationException异常参数。具体处理方式需按照系统的情况自定义。

Spring Security初识和表单认证(一) - Java技术债务

   登录后才可以发表评论呦...

专注分享Java技术干货,包括
但不仅限于多线程、JVM、Spring Boot
Spring Cloud、 Redis、微服务、
消息队列、Git、面试题 最新动态等。

想交个朋友吗
那就快扫下面吧


微信

Java技术债务

你还可以关注我的公众号

会分享一些干货或者好文章

Java技术债务