详解springSecurity之java配置篇

所属分类: 软件编程 / java 阅读数: 59
收藏 0 赞 0 分享

一 前言

本篇是springSecurity知识的入门第二篇,主要内容是如何使用java配置的方式进行配置springSeciruty,然后通过一个简单的示例自定义登陆页面,覆盖原有springSecurity默认的登陆页面;学习这篇的基础是 知识追寻者之前发布 过 的《springSecurity入门篇

二 java配置

2.1配置账号密码

如下所示, 使用 @EnableWebSecurity 在配置类上开启security配置功能; 在配置类中定义bean 名为 UserDetailsService, 主要是 负责 设置账号密码,拦截URL,校验成功后重定向至URL;如果要使用多用户,使用 manager.createUser 方法即可;

/**
 * @Author lsc
 * <p> </p>
 */
@EnableWebSecurity// 开启springSecurity
public class WebSecurityConfig {

  /* *
   * @Author lsc
   * <p> 主要是让SpringSecurity知道springSecurityFilterChain负责管理应用的URL
   * 校验,通过账号,密码的方式校验成功后重定向至应用;
   * </p>
   * @Param []
   */
  @Bean
  public UserDetailsService userDetailsService() throws Exception {
    //
    User.UserBuilder users = User.withDefaultPasswordEncoder();
    InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
    manager.createUser(users.username("user").password("user").roles("USER").build());
    manager.createUser(users.username("admin").password("admin").roles("USER","ADMIN").build());
    return manager;
  }

}

访问 localhost:8080/login 此时输入的密码就是 user , user ; 或者 admin, admin;

2.2 默认授权配置

如下所示 往配置类中 添加 配置类,其 继承 WebSecurityConfigurerAdapter, 重写 configure(HttpSecurity http) 方法, 此方便的作用就是Security 的授权过程,如下示例中,任何的请求都需要认证才可以访问,并且登陆页面还是security自带的登陆页面;

 @Configuration
  public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http
          .authorizeRequests(authorize ->
              authorize // 授权
              .anyRequest() // 任何请求
              .authenticated() // 认证认证
          )
          .formLogin(withDefaults()); //
    }
  }

2.3 过滤器顺序

再向配置中添加如下配置,其内容和上节内容差不多,但是 拦截的url 是 以/api 为开头的URL, 并且 是 ADMIN 角色才拥有访问权限; 使用@Order(1), 过滤器配置会优先走着条配置,其次才是上节 的配置;

  @Configuration
  @Order(1)
  public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
    protected void configure(HttpSecurity http) throws Exception {
      http
          .antMatcher("/api/**")
          .authorizeRequests(authorize -> authorize
              .anyRequest().hasRole("ADMIN")
          )
          .httpBasic(withDefaults())
          .formLogin(withDefaults());
    }
  }

控制层添加代码如下

 @GetMapping("api/login")
  public String login(){
    return "login";
  }

首先使用user用户访问 http://localhost:8080/api/login 账号密码校验成功后跳转应用请求url, 出现禁止页面,原因是user没有ADMIN角色权限;

然后使用admin用户登陆访问 http://localhost:8080/api/login 账号密码校验成功后跳转应用请求url 正常放问;

登陆页面如下

登陆成功后跳转如下

三 自定义登陆页面

3.1 实现自定页面登陆

自定义登陆页面 知识追寻者这边需要引入引擎模板依赖 , thymeleaf; application配置如下

spring:
 # 引擎模板配置
 thymeleaf:
  cache: false # 关闭缓存
  mode: HTML
  prefix: classpath:/templates/ # 指定 thymeleaf 模板路径
  encoding: UTF-8 # 指定字符集编码
 mvc:
  static-path-pattern: /static/** # js ,css 等静态文件路径

然后在templates 下新建 login.html , 内容如下

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
  <title>Please Log In</title>
</head>
<body>
<h1>Please Log In</h1>
<div th:if="${param.error}">
  Invalid username and password.</div>
<div th:if="${param.logout}">
  You have been logged out.</div>
<form th:action="@{/login}" method="post">
  <div>
    <input type="text" name="username" placeholder="Username"/>
  </div>
  <div>
    <input type="password" name="password" placeholder="Password"/>
  </div>
  <input type="submit" value="Log in" />
</form>
</body>
</html>

springSecurity授权配置内容如下,如下所示,loginPage 配置登陆页面,注意不要带上.html,loginProcessingUrl 配置登陆url,注意这边的url要与 login.html里面的action的url一致,否则会报错;后面就是successForwardUrl 登陆成功后的转发,当然还有登陆失败的转发failureForwardUrl(), 读者按需配置即可;

 @Configuration
  @Order(1)
  public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
    protected void configure(HttpSecurity http) throws Exception {
      http
          .antMatcher("/**")
          .authorizeRequests(authorize -> authorize
              .anyRequest().hasRole("USER")
          )
          .formLogin(form -> {
            form
                .loginPage("/login") // 配置登陆页
                .loginProcessingUrl("/login")
                .successForwardUrl("/login/success")// 登陆成功后会转发至 /login/success 请求
                .permitAll(); // 允许所有人访问
          })
          .csrf().disable()
          .httpBasic();// http请求方式 ,web 浏览器会弹出对话框

    }
  }

再将控制层内容替换如下啊,登陆逻辑就是我们请求 /login 会被转发至login.html, 然后action 提交至 /login, 这边已经到springSecurity 内部, 登陆成功后其会转发 至 /login/success;

 @GetMapping("/login")
  public String login() {
    return "login";
  }

  @PostMapping("/login/success")
  @ResponseBody
  public String success() {
    return "sucess";
  }

启动项目,浏览器输入http://localhost:8080/login 或者其它 ip + port + / path 会自动跳转至自定义 登陆页面

输入成功后会跳转的 /login/success ,返回内容如下

3.2 自定义登陆流程分析

来自官网的图片如下,是form表单登陆的流程,

  1. 首先客户端会发送未授权请求到服务端会被 FilterSecurityInterceptor 拦截标明为未授权的请求,抛出AccessDeniedException;
  2. ExceptionTranslationFilter 会捕获 AccessDeniedException 异常
  3. 此时 AuthenticationEntryPoint 会初始化配置流程;
  4. 捕获异常后并且重定向到登陆页面
  5. 最后 在登陆页面输入账号密码就会进入认证流程;

3.3 登陆认证流程分析

官网登陆时的认证流程图片如下

  • 账号密码输入成功后,UsernamePasswordAuthenticationFilter 就会创建UsernamePasswordAuthenticationToken;
  • AuthenticationManager储存着用户的信息,UsernamePasswordAuthenticationToken 会被送至这边进行认证;
  • 如果认证失败,SecurityContextHolder(主要是储存认证的数据,principle,credentials,authorities)会被清空, RememberMeServices.loginFail 与 AuthenticationFailureHandler都会被调用;
  • 如果登陆成功SessionAuthenticationStrategy 会被唤起重新定制下一次的登陆,认证信息会被储存至SecurityContextHolder,如果配置了remberMe, RememberMeServices.loginSuccess会被调用,ApplicationEventPublisher 会发布InteractiveAuthenticationSuccessEvent,AuthenticationSuccessHandler会被调用;

简单概括就是账号密码输入后进入认证流程,发放token, 在manager中认证,如果认证成功存储认证信息,否则清空认证信息;

四 参考文档

官方文档

https://docs.spring.io/spring-security/site/docs/5.3.3.BUILD-SNAPSHOT/reference/html5/#servlet-authentication-form

更多精彩内容其他人还在看

SpringBoot中使用Ehcache的详细教程

EhCache 是一个纯 Java 的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认的 CacheProvider。这篇文章主要介绍了SpringBoot中使用Ehcache的相关知识,需要的朋友可以参考下
收藏 0 赞 0 分享

在idea 中添加和删除模块Module操作

这篇文章主要介绍了在idea 中添加和删除模块Module操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

java spring整合junit操作(有详细的分析过程)

这篇文章主要介绍了java spring整合junit操作(有详细的分析过程),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

详解JAVA 弱引用

这篇文章主要介绍了 JAVA 弱引用的相关资料,帮助大家更好的理解和学习java引用对象,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

深入了解JAVA 虚引用

这篇文章主要介绍了JAVA 虚引用的相关资料,帮助大家更好的理解和学习JAVA,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

详解JAVA 强引用

这篇文章主要介绍了JAVA 强引用的相关资料,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

java中的按位与(&)用法说明

这篇文章主要介绍了java中的按位与(&)用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

深入了解JAVA 软引用

这篇文章主要介绍了JAVA 软引用的相关资料,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
收藏 0 赞 0 分享

利用MyBatis实现条件查询的方法汇总

这篇文章主要给大家介绍了关于利用MyBatis实现条件查询的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用MyBatis具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

Intellij IDEA 与maven 版本不符 Unable to import maven project See logs for details: No implementation for org.apache.maven.model.path.PathTranslator was bound

这篇文章主要介绍了Intellij IDEA 与maven 版本不符 Unable to import maven project See logs for details: No implementation for org.apache.maven.model.path.Pa
收藏 0 赞 0 分享
查看更多