• Spring Security:简单的保护一个SpringBoot应用程序(总结)


    Spring Security 在 Java类中的配置

    Spring Security使用 Java配置,可以轻松配置 Spring Security 而无需使用 XML 。

    Spring 3.1中,Java 类配置已添加到了 Spring 框架中,并在Spring 3.2中扩展到了Spring Security,并且定义了 JavaConfig 是带有@Configuration的类。

    Spring Boot Web 应用中使用 Spring Security,添加添加 Spring Boot Security 的依赖,Spring Boot 应用程序将自动要求所有 HTTP 端点都使用基本身份验证。

    使用 Maven 添加依赖:

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

    基本用法是示例:

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
       public void configureGlobal(AuthenticationManagerBuilder auth)
         throws Exception {
           auth.inMemoryAuthentication().withUser("user")
            .password("password").roles("USER");
      }
    }

    上面代码可以观察到,该身份验证配置了基于内存的身份验证。

    HTTP Security HTTP安全

     // 指定任何请求都需要经过身份验证后才能访问URLprotected void configure(HttpSecurity http) throws Exception {
       http.authorizeRequests()// 可以拥有多个子节点,和antMatcher()来定制URL访问规则
        .anyRequest().authenticated()// 指定任何请求都需要经过身份验证后才能访问URL
        .and().httpBasic();// 允许用户使用HTTP Basic身份验证进行身份验证
    }

    上面的默认配置可确保使用基于表单的登录名或HTTP基本身份验证来验证对应用程序的任何请求是否合法。

    它与以下 XML 配置完全相似:

    <http>
       <intercept-url pattern="/**" access="authenticated"/>
       <form-login />
       <http-basic />
    </http>

    题外话——HTTP基本认证的优缺点

    在HTTP中,基本认证(英语:Basic access authentication)是允许http用户代理(如:网页浏览器)在请求时,提供 用户名密码 的一种方式。

    在进行基本认证的过程里,请求的HTTP头字段会包含Authorization字段,形式如下: Authorization: Basic <凭证>,该凭证是用户和密码的组和的base64编码。

    优点:

    HTTP基本认证 是一种十分简单的技术,使用的是 HTTP头部字段 强制用户访问网络资源,而不是通过必要的 cookie、会话ID、登录页面等(非获取访问控制的)手段。

    基本上所有流行的网页浏览器都支持基本认证。基本认证很少在可公开访问的互联网网站上使用,有时候会在小型私有系统中使用(如路由器网页管理接口)。之后诞生的 HTTP摘要认证 用于替代基本认证,允许密钥以相对安全的方式在不安全的通道上传输。

    程序员和系统管理员有时会在可信网络环境中使用基本认证。由于,基本认证使用的是Base64可解码成明文,因此使用Telnet等网络协议工具进行监视时,可以直接获取内容,并用于诊断。

    缺点:

    基本认证 并没有为传送凭证(英语:transmitted credentials)提供任何机密性的保护。仅仅使用 Base64 编码并传输,而没有使用任何 加密散列算法。因此,基本认证常常和 HTTPS 一起使用,以提供机密性

    现存的浏览器保存认证信息直到标签页或浏览器被关闭,或者用户清除历史记录。HTTP没有为服务器提供一种方法指示客户端丢弃这些被缓存的密钥。这意味着服务器端在用户不关闭浏览器的情况下,并没有一种有效的方法来让用户退出。

    同时 HTTP 并没有提供退出机制。但是,在一些浏览器上,存在清除凭证(credentials )缓存的方法。

    FormLogin 表单登录 和 Authorization With Roles 角色授权

    Spring Security 基于已启用的功能并使用处理提交的登录名的 URL 的标准值自动生成一个登录页面:

    protected void configure(HttpSecurity http) throws Exception {
       http.authorizeRequests() // 可以拥有多个子节点,和antMatcher()来定制URL访问规则
        .antMatchers("/login/**").permitAll()// 允许所有人匿名访问"/login*"登录页面; ant-style path patterns ANT样式路劲匹配器 有 *,**,? 这三种通配符
        .antMatchers("/admin/**").hasRole("ADMIN") // "/admin/"路径下的URL只允许ROLE_ADMIN角色才能访问
        .anyRequest().authenticated() // 指定任何请求都需要经过身份验证后才能访问URL
        .and().formLogin()// 允许用户使用基于表单的登录进行身份验证
        .loginPage("/login").permitAll();// 指定登录页路径并允许所有角色访问
    }

    在这里,自动生成的登录页面便于快速启动和运行。还有如何通过访问使用类型安全的API(hasRole)以及基于表达式的 API。请注意,antMatchers() 元素的顺序很重要,需要首先制定更具体的规则,然后是更通用的规则

    几种方法可以用来配置表单登录.formLogin()的行为:

    • loginPage()自定义登录页面

    • loginProcessingUrl() –将用户名和密码提交到的URL

    • defaultSuccessUrl() -成功登录后的登录页面

    • failureUrl() –登录失败后的登录页面

    @Override
    protected void configure(HttpSecurity http) throws Exception {
       http.formLogin()
        .loginPage("/login.html")
        .loginProcessingUrl("/perform_login")
        .defaultSuccessUrl("/homepage.html",true)
        .failureUrl("/login.html?error=true")
    }

     

    Logout 登出

    与 Spring Security 的许多其他方面一样,框架有提供默认的出色的注销功能。默认情况下,注销请求会使会话无效清除所有身份验证缓存清除 SecurityContextHolder重定向到登录页面

    protected void configure(HttpSecurity http) throws Exception {
       http.logout();
    }

    但是,如果你想进一步地控制可靠的处理程序,可以看下面这段更完整的实现:

    protected void configure(HttpSecurity http) throws Exception {
       http.logout().logoutUrl("/my/logout")
        .logoutSuccessUrl("/my/index")
        .logoutSuccessHandler(logoutSuccessHandler) // 注销成功handler
        .invalidateHttpSession(true)// 控制会话无效
        .addLogoutHandler(logoutHandler)// 注销失败handler
        .deleteCookies(cookieNamesToClear)// 用户注销时要删除的cookie列表
        .and()
         // some other method calls
    }

    Spring Security 的一些认证方式

    基于内存的认证

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)
     throws Exception {
       auth.inMemoryAuthentication()
        .withUser("user").password("password").roles("USER")
        .and()
        .withUser("admin").password("password").roles("USER", "ADMIN");
    }

    JDBC验证,需要在应用程序中定义一个数据源

    @Autowired
    private DataSource dataSource;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)
     throws Exception {
       auth.jdbcAuthentication().dataSource(dataSource)
        .withDefaultSchema() // 默认用户Schema
        .withUser("user").password("password").roles("USER")
        .and()
        .withUser("admin").password("password").roles("USER", "ALADMIN");
    }

    关于用户Schema,UserDetailsServiceJdbcDaoImpl)的标准JDBC实现要求表为用户加载密码,帐户状态(启用或禁用)和权限列表(角色)。你将需要调整此架构以匹配你在正在使用的数据库方言或驱动(将某个应用程序与某个数据库管理系统连接)。(参考1

    create table users(
      username varchar_ignorecase(50) not null primary key,
      password varchar_ignorecase(50) not null,
      enabled boolean not null
    );

    create table authorities (
      username varchar_ignorecase(50) not null,
      authority varchar_ignorecase(50) not null,
      constraint fk_authorities_users foreign key(username) references users(username)
    );
    create unique index ix_auth_username on authorities (username,authority);

    题外话——在MySQL中,SchemaDatabase是同义词。你可以用MySQL SQL语法SCHEMA代替关键字DATABASE,例如使用CREATE SCHEMA代替CREATE DATABASE。其他一些数据库产品也有区别。例如,在Oracle数据库产品中,Schema仅代表Database的一部分:单个用户拥有的表和其他对象。你可以在MySQL数据库下验证一下:

    CREATE SCHEMA `test_schema`;
    CREATE DATABASE `test_database`;

    然后你会发现这两者在物理上是一样的效果,可以用 MySQL SQL 语法SCHEMA代替关键字DATABASE,例如使用CREATE SCHEMA代替CREATE DATABASE都创建了一个数据库。不同的RDBMS中,SchemaDatabase不一定是一样的概念。关于MySQL中对这更详细的描述,请参考这里

    注意一点,withDefaultSchema指令提供的DDL脚本使用了不适合MySQL的方言,项目启动时会报嵌套的java.sql.SQLSyntaxErrorException异常。(参考2

    解决方案:(不使用withDefaultSchema

        auth.jdbcAuthentication()
                  .dataSource(dataSource)
                  .usersByUsernameQuery(
                           "select username,password, enabled from users where username=?")
                  .authoritiesByUsernameQuery(
                           "select username, role from user_roles where username=?");

     

    使用LDAP(Lightweight Directory Access Protocol,轻量级目录访问协议)验证用户(参考3

      @Override
     public void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth
        .ldapAuthentication()
          .userDnPatterns("uid={0},ou=people")
          .groupSearchBase("ou=groups")
          .contextSource()
            .url("ldap://localhost:8389/dc=springframework,dc=org")
            .and()
          .passwordCompare()
            .passwordEncoder(new BCryptPasswordEncoder())
            .passwordAttribute("userPassword");
    }

    这个协议它是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。目录服务在开发内部网和与互联网程序共享用户、系统、网络、服务和应用的过程中占据了重要地位。

    LDAP的一个常用用途是单点登录,用户可以在多个服务中使用同一个密码,通常用于公司内部网站的登录中(这样他们可以在公司电脑上登录一次,便可以自动在公司内部网上登录)。(LDAP实践参考

  • 相关阅读:
    springboot系列九,springboot整合邮件服务、整合定时任务调度
    springboot系列八、springboot整合kafka
    springboot系列六、springboot配置错误页面及全局异常
    springboot系列五、springboot常用注解使用说明
    springboot系列四、配置模板引擎、配置热部署
    springboot系列三、springboot 单元测试、配置访问路径、多个配置文件和多环境配置,项目打包发布
    springboot系列二、springboot项目搭建
    springboot系列一、springboot产生背景及介绍
    kafka系列十、kafka常用管理命令
    Jmeter4.X
  • 原文地址:https://www.cnblogs.com/magic-sea/p/12824718.html
Copyright © 2020-2023  润新知