《Spring Security 实战》学习:建立简单的Spring Security项目

参考教程:陈木鑫老师的《Spring Security 实战》html

建立spring boot项目

经过Intellij IDEA建立Spring Boot项目的方式有许多种,其中最简单的方式就是使用Spring Initializr
工具。
Spring Initializr 容许咱们提早选定一些经常使用的项目依赖,此处咱们选择 Security 做为构建Spring
Security项目的最小依赖,选择Web做为Spring Boot构建Web应用的核心依赖。
在这里插入图片描述
Next :
在这里插入图片描述
Next:
在这里插入图片描述
建立项目的目录结构:
在这里插入图片描述前端

maven 引用

在自动构建的Spring Security 项目中,Spring Initializr 为咱们引入了如下依赖:java

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

咱们点开spring-boot-starter-security能够看到,其包含了如下依赖:web

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter</artifactId>
      <version>2.3.1.RELEASE</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
      <scope>compile</scope>
    </dependency>

其中 spring-security-webspring-security-config两个核心模块,正是官方建议引入的Spring Security最小依赖。spring

声明controller

在项目中声明一个测试路由TestController后端

package com.haan.springsecuritydemo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping
    public String hello(){
        return "Hello Spring Security!";
    }
}

在这里插入图片描述

运行SpringsecuritydemoApplication

运行SpringsecuritydemoApplication,默认启动 8080 端口,打开浏览器,访问localhost:8080,咱们发现页面跳转到了localhost:8080/login:
在这里插入图片描述
在引入Spring Security项目以后,虽然没有进行任何相关的配置或编码,但Spring Security有一个默认的运行状态,要求在通过表单基本认证后才能访问对应的URL资源,其默认使用的用户名为 user ,密码则是动态生成并打印到控制台的一串随机码。翻看控制台的打印信息:
在这里插入图片描述
输入用户名和密码后,单击“登陆”按钮便可成功访问:
在这里插入图片描述浏览器

修改登陆信息

基本表单认证中,用户名和密码都是能够配置的,最多见的就是在resources下的application配置文件中修改:安全

spring.security.user.name=user02
spring.security.user.password=aaaaaa

从新启动程序,发现控制台再也不打印默认密码串了,此时使用咱们自定义的用户名和密码便可登陆。服务器

WebSecurityConfigurerAdapter

protected void configure(HttpSecurity http) throws Exception {
        this.logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");
        ((HttpSecurity)((HttpSecurity)((AuthorizedUrl)http.authorizeRequests().anyRequest()).authenticated().and()).formLogin().and()).httpBasic();
    }

能够看到 WebSecurityConfigurerAdapter 已经默认声明了一些安全特性:app

  • 验证全部请求。
  • 容许用户使用表单登陆进行身份验证(Spring Security 提供了一个简单的表单登陆页面)。
  • 容许用户使用HTTP 基本认证。

spring boot 默认定义了DefaultConfigurerAdapter ,由@ConditionalOnMissingBean可知当没有其余WebSecurityConfigurerAdapter被定义时,将使用DefaultConfigurerAdapter

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({WebSecurityConfigurerAdapter.class})
@ConditionalOnMissingBean({WebSecurityConfigurerAdapter.class})
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
public class SpringBootWebSecurityConfiguration {
    public SpringBootWebSecurityConfiguration() {
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @Order(2147483642)
    static class DefaultConfigurerAdapter extends WebSecurityConfigurerAdapter {
        DefaultConfigurerAdapter() {
        }
    }
}

自定义表单登陆页

Spring boot提供了WebSecurityConfigurerAdapter 的默认实现DefaultConfigurerAdapter,可以提供基本表单登陆认证。

虽然自动生成的表单登陆页能够方便、快速地启动,可是大多数应用程序更但愿提供本身的表单登陆页,此时就须要咱们提供本身的WebSecurityConfigurerAdapter来代替DefaultConfigurerAdapter,覆写WebSecurityConfigurerAdapterconfigure方法:

@EnableWebSecurity
public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/myLogin.html")    //指明登陆页面
                .permitAll()    //指明登陆页容许全部进行访问
                .and()
                .csrf().disable();
    }
}
  • authorizeRequests()方法实际上返回了一个 URL 拦截注册器,咱们能够调用它提供的anyRequest()antMatchers()regexMatchers()等方法来匹配系统的URL,并为其指定安全策略。
  • formLogin()方法和httpBasic()方法都声明了须要Spring Security提供的表单认证方式,分别返回对应的配置器。其中formLogin().loginPage("/myLogin.html")指定自定义的登陆

/myLogin.html,同时,Spring Security会用/myLogin.html注册一个POST路由,用于接收登陆请求。

  • csrf()方法是Spring Security提供的跨站请求伪造防御功能,当咱们继承WebSecurityConfigurer Adapter时会默认开启 csrf()方法。

访问localhost:8080 ,咱们发现,页面就跳转到了localhost:8080/myLogin.html,因为咱们静态文件中并无myLogin.html 文件,因此提示了一个404的white page:
在这里插入图片描述
咱们在resources/static 文件夹下建立页面myLogin.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello Security!</title>
</head>
<body>
    <h3>登陆页</h3>
    <form action="/myLogin.html" method="post">
        <input type="text" name="username"> <br/>
        <input type="text" name="password"> <br/>
        <input type="submit" value="login">
    </form>
</body>
</html>

重启服务,再次访问localhost:8080:
在这里插入图片描述
输入上面的application.properties中配置的用户登陆帐户和密码进行登陆,登录成功:
在这里插入图片描述

其余表单配置项

指定登陆处理URL

在自定义表单登陆页以后,处理登陆请求的URL也会相应改变,默认状况下,
若是只配置loginPage而不配置loginProcessingUrl的话那么loginProcessingUrl默认就是loginPage,若是须要自定义登陆请求的URL,须要配置loginProcessingUrl:

重启登陆,咱们发现中间访问了localhost:8080/myLogin
在这里插入图片描述

补充:loginPageloginProcessingUrl

  • 二者都不配置:默认都是/login
  • 二者都配置:按本身的来
  • 只配置loginProcessingUrlloginPage默认/login
  • 只配置loginPage: loginProcessingUrl默认就是loginPage

设置登陆成功处理

此时,有些读者可能会有疑问,由于按照惯例,在发送登陆请求并认证成功以后,页面会跳转回原访问页。在某些系统中的确是跳转回原访问页的,但在部分先后端彻底分离、仅靠JSON完成全部交互的系统中,通常会在登陆时返回一段 JSON 数据,告知前端成功登陆成功与否,由前端决定如何处
理后续逻辑,而非由服务器主动执行页面跳转。这在Spring Security中一样能够实现。

表单登陆配置模块提供了 successHandler()failureHandler()两个方法,分别处理登陆成功和登陆失败的逻辑。

  • successHandler()方法带有一个Authentication参数,携带当前登陆用户名及其角色等信息;
  • failureHandler()方法携带一个AuthenticationException异常参数。具体处理方式需按照系统的状况自定义。
@EnableWebSecurity
public class MyWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/myLogin.html") //指明登陆页面
                .loginProcessingUrl("/myLogin")   //指明处理登录的URL路径,即登录表单提交请求
                .successHandler(new AuthenticationSuccessHandler() {        // 设置登陆成功的处理器
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        PrintWriter responseWriter = httpServletResponse.getWriter();
                        String name = authentication.getName();
                        responseWriter.write(name+" login success!");
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {        // 设置登陆失败的处理器
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        PrintWriter responseWriter = httpServletResponse.getWriter();
                        responseWriter.write("login error!");
                    }
                })
                .permitAll()    //指明登陆页容许全部进行访问
                .and()
                .csrf().disable();
    }
}

正确的帐号密码:
在这里插入图片描述
错误的帐号密码:
在这里插入图片描述

相关文章
相关标签/搜索