Spring Security学习与探究系列(一):快速上手Spring Security

简介

为了督促自己的学习,新开一个坑,就是记录对Spring Security的探究与学习。使用Spring Security的目的是,之前实现后端时,用户验证与鉴权都是手动实现的而过于繁琐。后来了解到了Spring Security对Web的安全有很好的支持,因此打算系统地学习一下Spring Security,并将学习过程中的思考和见解一并分享出来,欢迎批评指出。

什么是Spring Security

先读官方文档对其的定义:

Spring Security是一个框架,提供了身份验证、授权和针对常见攻击的保护。

Spring Security是一个轻量级的安全框架,能为基于Spring的Java Web应用程序的安全提供保证。Spring Security能与Spring MVC很好地集成,因此如果项目是基于Spring搭建的,那么在原本项目的基础上加入Spring Security来进行安全校验是一个较好的选择。

快速开始

我们先来快速地搭建一个基础项目,实现Spring Security所提供的功能吧。首先,笔者所使用的的环境和IDE具体为:

  1. AdoptOpenJDK 11
  2. IntelliJ IDEA 2020.1.2 x64

推荐使用IDEA新建项目中选项中的Spring Initializr,使用该初始化器能够快速地搭建一个SpringBoot项目,并且可以自由地选择将要使用的组件,本文选择Spring Security组件。生成项目后,打开pol.xml文件看一下:

<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>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

需要注意的是,本文所使用的的SpringBoot版本为2.4.5。

此时,直接运行该SpringBoot项目,打开浏览器访问localhost:8080/login,可以看到如下画面:
默认页面
这是Spring Security为我们默认生成的登录页面,并且用户名是user,密码是IDEA控制台打印出来的一串密码。到目前为止,Spring Security已经快速地集成到我们的项目中了,但这一切都是默认提供的,我们希望能够使用自定义的登录页面。下面介绍Spring Security的进一步使用。

往前一步

Spring Security提供了灵活的可定制化的配置,可以根据项目具体情况来进行不同的配置以实现不同的安全功能。Spring Security中进行配置的操作是在WebSecurityConfigurerAdapter,我们只需要继承该类,并重写configure方法即可。本文不会对各种类和接口进行繁琐的介绍,力求最快速地实现。因此下面我们介绍怎么样自定义登录页面。

Step.1 准备前端页面

我们先准备几个需要访问的页面,分别是登录页面、登录成功页面和登录失败页面。显然,登录成功和登录失败的页面是需要验证才能访问的,而登录页面则不需要任何的验证。下面的HTML页面均放置于resources/templates文件夹下。
1. login.html

<!DOCTYPE html>
<html lang="cn">
<head>
    <meta charset="UTF-8">
    <title>简单登录页面</title>
</head>
<body>
<h3>简易表单登录</h3>
<form action="/doLogin" method="post">
    <table>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="myUsername"></td>
        </tr>
        <tr>
            <td>密码:</td>
            <td><input type="password" name="myPassword"></td>
        </tr>
        <tr>
            <td colspan="10"><button type="submit" style="width: 100%; margin-top: 10px">登录</button></td>
        </tr>
    </table>
</form>
</body>
</html>

简单的登录页面,仅有一个表单、两个输入框和一个按钮。这里需要注意的是,表单的action属性设置为了doLogin,代表了表单提交的目标URL地址。

2. success.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录成功</title>
</head>
<body>
<h3>登录成功!</h3>
<div style="display: flex">
    <p>用户名:</p><p th:text="${username}"></p>
</div>
</body>
</html>

这里笔者使用了thymeleaf,打印出username
3. failure.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录失败页面</title>
</head>
<body>
<h3>登录失败页面</h3>
<div style="display: flex">
    <p>失败原因:</p><p th:text="${error}"></p>
</div>
</body>
</html>

这里笔者同样使用了thymeleaf,打印出error

Step.2 准备控制器

新建一个TestController,实现接口地址到View视图的映射。

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.WebAttributes;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import java.security.Principal;

@Controller
public class TestController {

    @RequestMapping(value = "/success")
    public ModelAndView success(){
        String username = null;
        Object object = SecurityContextHolder.getContext().getAuthentication().getPrincipal();  //取出身份信息
        if (object instanceof UserDetails){
            UserDetails userDetails = (UserDetails) object;
            username = userDetails.getUsername();
        }else {
            Principal principal = (Principal) object;
            username = principal.getName();
        }
        return new ModelAndView("/success", "username", username);
    }

    @RequestMapping(value = "/failure")
    public ModelAndView failure(HttpServletRequest request){
        AuthenticationException authenticationException = (AuthenticationException)
                request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);  //取出错误信息
        return new ModelAndView("/failure", "error", authenticationException.getLocalizedMessage());
    }

    @RequestMapping(value = "/login")
    public String  login(){
        return "login";
    }
}

由于笔者使用了thymeleaf,这里声明的接口地址,如/success等,Spring会到resources/templates文件夹下寻找对应的HTML文件。

Step.3 配置Spring Security

新建一个SecurityConfig文件,如下所示:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();  //关闭CSRF验证
        http.authorizeRequests().anyRequest().authenticated();  //对所有接口都进行拦截
        http.formLogin()
                .loginPage("/login")             //自定义Login登录页面
                .usernameParameter("myUsername") //自定义username的参数名称
                .passwordParameter("myPassword") //自定义password的参数名称
                .loginProcessingUrl("/doLogin")  //定义的表单提交后的中转地址
                .defaultSuccessUrl("/success")   //验证成功后跳转的地址
                .failureUrl("/failure")          //验证失败跳转的地址
                .permitAll();                    //与表单登录相关的接口不拦截
    }
}

配置很简单,这里实现了对登录页面的修改,并且实现了登录成功/登录失败后要跳转到哪个页面。

我们运行程序,在浏览器打开localhost:8080/login,即可以看到如下图所示的页面。可以看出,Spring Security默认提供的登录页面已经被修改为我们自己实现的Login页面了。
简易登录页面
我们先随便输入用户名和密码,此时会验证失败而跳转到失败的页面,如下图所示:
验证失败
我们输入正确的用户名和密码,即user和IDEA控制台给出的密码,会跳转到成功的页面,如下图所示:
验证成功
到目前为止,已经实现了Spring Security的登录页面的简单定制。在上述流程中,我们使用的是默认的账号User以及生成的密码。除此之外,我们还能添加不同的账户,比如我们在系统中添加一个admin:admin账号,需要重写SecurityConfig#configure(AuthenticationManagerBuilder)方法:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("admin").password(new BCryptPasswordEncoder().encode("admin")).roles("admin");
    }
}

上述代码的含义是,在内存中新增一个admin账号,且密码是admin,使用BCryptPasswordEncoder对密码加密,同时该账号拥有的角色是admin,表面了该账号拥有哪些权限。重新启动项目后,便能使用admin账号来登录系统了。

小结

本文快速地介绍了怎么使用Spring Security,并以一个简单的例子来介绍了怎样更换Spring Security默认的登录页面。但到目前为止,我们使用的账号与密码是系统自带的,在实际中,账号数据应该从数据库中导入,而不是硬编码在程序中。在下一篇文章中,笔者将介绍在Spring Security中怎样使用数据库中的账户数据来实现身份和权限的校验。感谢你的阅读~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值