Spring Security 安全框架概述 与 快速入门

目录

Spring Security 安全框架概述

Spring Security 快速入门

自定义默认账号名称与密码

内存用户认证与授权

Spring Security 用户注销


Spring Security 安全框架概述

1、Java web 应用中安全框架使用率高的莫过于 Spring-security 与 Apache Shiro

1、Spring-security 官网:Spring Security
2、Spring-security gitHub 开源地址:https://github.com/spring-projects/spring-security/

2、Spring Security 是 Spring 官网的顶级项目,与 spring boot、spring data、spring cloud 等齐名。

3、Spring Security 是一个专注于向 Java 应用程序提供身份验证和授权的安全框架,与所有 Spring 项目一样,Spring Security 的真正威力在于它可以很容易地扩展以满足定制需求。Spring Security 是采用 AOP 思想,基于 servlet 过滤器实现的。

4、Spring Security 是 Spring Boot 底层安全模块默认的技术选型,可以实现强大的 web 安全控制,对于安全控制,仅需引入spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理。

5、Spring Security Features(特性):

1、全面和可扩展的身份验证和授权支持(Comprehensive and extensible support for both Authentication and Authorization)
2、防止攻击,如会话固定,点击劫持,跨站请求伪造等(Protection against attacks like session fixation, clickjacking, cross site request forgery, etc)
3、Servlet API 的集成(Servlet API integration)
4、与 Spring Web MVC 的可选集成(Optional integration with Spring Web MVC )
认证 & 授权
应用程序安全的两个主要区域是“认证”和“授权”,spring security 的主要核心功能也是认证和授权。
 认证(Authentication) 用户认证指的是验证某个用户是否为系统中的合法主体,即用户能否访问该系统。用户认证一般要求用户提供账号和密码,系统通过校验账号和密码来完成认证过程。
授权(Authorization用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限通常是不同的,比如有的用户只能读,有的用户能读能写。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。  
Web & 安全
 登陆/注销HttpSecurity 配置登陆、注销功能
Thymeleaf 提供 SpringSecurity 标签支持

需要引入thymeleaf-extras-springsecurity4

sec:authentication=“name” 获得当前用户的用户名

sec:authorize=“hasRole(‘ADMIN’)” 当前用户必须拥有 ADMIN权 限时才会显示标签内容

remember me()

表单添加 remember-me 的 checkbox

配置启用 remember-me 功能

CSRF(Cross-site request forgery)跨站请求伪造HttpSecurity 启用 csrf 功能,会为表单添加 _csrf 的值,提交携带来预防 CSRF

Spring Security 快速入门

1、环境:IDEA 14 + Java JDK 1.8 + Spring Boot 2.1.3.RELEASE +  Spring Security 5.1.4 + Apache Maven 3.5.2

2、pom.xml 文件中导入 Spring Security 依赖内容如下(官网 Spring Boot with Maven)

<!-- Spring security 安全组件-->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

 pom.xml · 汪少棠/thymeleafapp - Gitee.com

1、当没有导入 spring security 组件时,Spring boot 4 大静态资源目录下的资源以及 templates 下的 index.html 都可以从浏览器直接访问,但是一旦导入就无法直接访问了。

2、spring security 导入后默认已经开启了验证,必须先登录验证通过后才能访问(包括静态资源),当不做任何配置时,security 提供默认的账号为 "user"、登录的密码在应用启动时会随机生成并打印在控制台,格式如:Using generated security password: 4f4785b7-aadb-4aab-9b2f-d32749d06460

1、当用户未登录时,默认无论什么请求都会自动跳转到 Security 的 /login 进行登录操作,登录错误时会自动跳转到 /login?error,这些都是 Security 集成好了的。

2、默认的登陆页面使用的是在线的 bootstrap 样式,所以如果没有网络,则也就没有了样式。

官方文档:Java Configuration and Form Login

自定义默认账号名称与密码

1、导入 spring security 未做任何配置时,默认使用账号名称为 user,密码是启动时随机生成的,现在在全局配置文件中对它们进行修改。

2、在 spring boot 官网中可以找到如下 security properties 配置项:

# ----------------------------------------
# SECURITY PROPERTIES
# ----------------------------------------
# SECURITY (SecurityProperties)
spring.security.filter.order=-100 # Security filter chain order.
spring.security.filter.dispatcher-types=async,error,request # Security filter chain dispatcher types.
spring.security.user.name=user # Default user name.默认用户名为 user
spring.security.user.password= # Password for the default user name. 账号的密码,默认是自动随机生成
spring.security.user.roles= # Granted roles for the default user name. 默认用户角色

# SECURITY OAUTH2 CLIENT (OAuth2ClientProperties)
spring.security.oauth2.client.provider.*= # OAuth provider details.
spring.security.oauth2.client.registration.*= # OAuth client registrations.

# SECURITY OAUTH2 RESOURCE SERVER (OAuth2ResourceServerProperties)
spring.security.oauth2.resourceserver.jwt.jwk-set-uri= # JSON Web Key URI to use to verify the JWT token.
   spring.security.oauth2.resourceserver.jwt.issuer-uri= # URI that an OpenID Connect Provider asserts as its Issuer Identifier.

3、现在在 application.yml 文件配置如下(application.yml 也是同理):

spring:
  security:
    user:
      name: admin  # spring security 安全认证的默认账号与密码
      password: 123456

src/main/resources/application.yml · 汪少棠/thymeleafapp - Gitee.com 

4、再次启动应用进行访问,此时必须使用配置好的账号与密码登录。

内存用户认证与授权

1、下面先使用内存用户来简单体验一下  Spring Security 的玩法,内存用户是指用户数据存储在内存中,区别于数据库用户。

2、新建一个 PersonControler,提供增删改查方法从浏览器访问,路径如下:

http://localhost:8080/person/findById/1     :根据 id 查询用户
http://localhost:8080/person/lists          :查询所有用户
http://localhost:8080/person/add              :添加用户
http://localhost:8080/person/update         :修改用户
http://localhost:8080/person/del/2             :删除用户

3、现在实现如下需求(用户 分配 角色,角色 分配 权限):

1、有 3 个用户:zhangSanFeng(张三丰) 、zhangCuiShan(张翠山)、zhangWuJi(张无忌)
2、有 3 个角色:administrators(管理员)、auditor(审核员)、operator(操作员)
3、角色对应的权限如下:
    3.1、administrators 能访问所有请求
    3.2、auditor 能查询、修改
    3.3、operator 能查询、添加
4、为 zhangSanFeng 分配 administrators 角色,zhangCuiShan 分配 auditor、operator 角色,zhangWuJi 分配 operator 角色 .

3、自定义类继承 WebSecurityConfigurerAdapter,然后重写 configure 方法配置认证与授权。

/**
 * Spring security 安全框架配置
 * 1、 WebSecurityConfigurerAdapter(抽象类) implements 了 WebSecurityConfigurer<WebSecurity>
 * 2、@EnableWebSecurity :表示开启 Spring Security 安全认证与授权
 *
 * @author wangmaoxiong
 * @version 1.0
 * @date 2020/5/20 20:39
 */
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 定义用户认证规则
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /**inMemoryAuthentication():添加内存用户认证,这些账号密码只存储在内存中,而不是数据库。
         * jdbcAuthentication():JdbcUserDetailsManagerConfigurer 数据库用户认证。
         * <p>
         * .passwordEncoder(PasswordEncoder passwordEncoder):密码编码,Spring Security 高版本必须进行密码编码,否则报错
         * .withUser(String username):添加用户名称,返回 UserDetailsBuilder
         * .password(String password):为用户添加密码,不能为 null
         * .roles(String... roles):为用户添加角色,一个用户可以有多个角色.
         * .and():返回对象本身,方便链式编程,也可以分开写
         * </p>
         */
        auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder())
                .withUser("zhangSanFeng").password("123456").roles("administrators")
                .and()
                .withUser("zhangCuiShan").password("123456").roles("auditor", "operator")
                .and()
                .withUser("zhangWuJi").password("123456").roles("operator");
    }

    /**
     * 定义授权规则
     *
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /**
         * .authorizeRequests:表示验证请求
         * .antMatchers(String... antPatterns):使用 {@link AntPathRequestMatcher} 的匹配规则
         * .antMatchers("/") : 表示应用的首页,/user/toLogin 用于进入自定义登陆页
         * .permitAll():表示允许一切用户访问,底层调用 access("permitAll")
         * .hasRole(String role):表示 antMatchers 中的 url 请求允许此角色访问
         * .hasAnyRole(String... roles) : 表示 antMatchers 中的 url 请求允许这多个角色访问
         * .access(String attribute):表示允许访问的角色,permitAll、hasRole、hasAnyRole 底层都是调用 access 方法
         * .access("permitAll") 等价于 permitAll()
         * "/**" 表示匹配任意
         */
        http.authorizeRequests().antMatchers("/user/toLogin").permitAll();
        http.authorizeRequests()
                .antMatchers("/person/del/**").hasRole("administrators")
                .antMatchers("/person/update").hasAnyRole("administrators", "auditor")
                .antMatchers("/person/add").hasAnyRole("administrators", "operator")
                .antMatchers("/person/findById/**", "/person/lists").access("permitAll");

        /**
         * spring security 导入后默认已经开启了验证,包括静态资源
         * 因为登陆页面也需要引用静态资源,所以将登录页面的静态资源进行放行,运行一切用户访问.
         */
        http.authorizeRequests().antMatchers("/css/**", "/images/**", "/js/**").permitAll();
        /**
         * http.authorizeRequests().anyRequest().hasRole("operator"):
         *      表示约定以外的所有请求,都需要有 operator 角色才可以访问
         * http.authorizeRequests().anyRequest().authenticated():
         *      表示约定以外的所有请求,必须要经过认证才能访问,但是认证的可以是任意角色,即只要认证就行,与角色的权限无关
         * http.authorizeRequests().anyRequest().permitAll():
         *      表示约定以外的所有请求,任何用户都可以访问.
         */
        http.authorizeRequests().anyRequest().permitAll();

        /**
         * 1、formLogin():指定支持基于表单的身份验证
         * 2、未使用 FormLoginConfigurer#loginPage(String) 指定登录页时,将自动生成一个登录页面,亲测此页面引用的是联网的 bootStrap 的样式,所以断网时,样式会有点怪
         * 3、当用户没有登录、没有权限时默认会自动跳转到登录页面(默认 /login),当登录失败时,默认跳转到 /login?error,登录成功时会放行
         */
        http.formLogin().loginPage("/user/toLogin");

        /**
         * 默认开启了注销功能,默认以 "/logout" 路劲表示用户注销请求,
         * 注销成功后,默认跳转到 "/login?logout" 登录页面,自动清除 session,清除记住我功能的 Cookie,HttpSession 无效。
         */
        http.logout().logoutUrl("/logout").permitAll();

        /**
         * 开启记住我功能。
         * 1、开启后登陆按钮上方自动会显示一个 "记住我" 复选框
         * 2、登陆成功后, 浏览器会自动存储一个名称为 remember-me 的 cookie 数据,过期时间为 14 天
         * 3、有效期内用户再次访问系统时就会带上这个 cookie,只要验证通过,就可以免登录,直接进入系统
         * 4、当 logout 注销时,默认会自动删除此 cookie 数据
         */
        http.rememberMe();

        /**Spring Security 的 CSRF 防护默认开启,如果是 POST 请求,则必须验证 Token,如果没有,就会报错 403,无权限访问,即使上面对目标请求路径授权了也不行
         * 要么就是 post 请求时带上 csrf 需要的 token 信息,要么就需要直接关闭 csrf 防护。
         * CsrfConfigurer<H> ignoringAntMatchers(String... antPatterns):对指定的请求不使用 CSRF 保护,即使它们在 requireCsrfProtectionMatcher(RequestMatcher)} 中匹配。
         * CsrfConfigurer<H> ignoringRequestMatchers(RequestMatcher... requestMatchers): 对指定的请求不使用 CSRF 保护,即使它们在 requireCsrfProtectionMatcher(RequestMatcher)} 中匹配。
         * CsrfConfigurer<H> requireCsrfProtectionMatcher(RequestMatcher requireCsrfProtectionMatcher): 对指定的请求使用 CSRF 保护。默认忽略 GET、HEAD、TRACE、OPTIONS 请求,并处理所有其他请求。
         */
        http.csrf().disable();
    }
}

/**
 * 密码编码。Spring Security 高版本必须进行密码编码,否则报错
 */
class MyPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence charSequence) {
        return charSequence.toString();
    }

    @Override
    public boolean matches(CharSequence charSequence, String s) {
        return s.equals(charSequence.toString());
    }
}

src/main/java/com/wmx/thymeleafapp/config/WebSecurityConfig.java · 汪少棠/thymeleafapp - Gitee.com

1、关于 URL 地址的 AntPathRequestMatcher 匹配规则,可以参考官网文档:AntPathMatcher.html,其实和正则表达式的规则基本差不多。在线演示源码
2、Forbidden:不允许的,被禁止的。表示权限不足,这里因为没有配置错误页面,所以直接显示错误信息。
3、开启内存用户后,全局配置文件中 spring.security.user.name 与 password 配置用户会失效。

Spring Security 用户注销

1、使用 WebSecurityConfigurerAdapter 配置适配器时,会自动应用注销功能,默认情况下,访问 /logout 将通过以下方式注销用户:

使 HTTP 会话无效清除已配置的所有 RememberMe(记住我) 身份验证
清除 SecurityContextHolder重定向到 /login?logout

2、不过,与配置登录功能类似,可以使用各种选项进一步自定义注销要求,开启自动注销功能只需要设置 logout() 方法即可,下面是官方文档(Handling Logouts)给出的示例:

protected void configure(HttpSecurity http) throws Exception {
    http
        .logout()                                                               
            .logoutUrl("/my/logout")                                               
            .logoutSuccessUrl("/my/index")                                          
            .logoutSuccessHandler(logoutSuccessHandler)                             
            .invalidateHttpSession(true)                                            
            .addLogoutHandler(logoutHandler)                                        
            .deleteCookies(cookieNamesToClear)                                     
            .and()
        ...
}
logout提供注销支持,使用 WebSecurityConfigurerAdapter 时会自动应用此选项,即不写时默认也支持注销功能
logoutUrl触发注销的 URL(默认为 /logout),如果启用了 CSRF 保护(默认),则注销请求也必须是 POST。JavaDoc.
logoutSuccessUrl注销后要重定向到的 URL, 默认值是 /login?logout. JavaDoc.
logoutSuccessHandler自定义 LogoutSuccessHandler, 如果指定了此选项,则忽略 logoutSuccessUrl()
invalidateHttpSession指定在注销时是否使 HttpSession 无效, 默认为 true.
addLogoutHandler添加 LogoutHandler,默认情况下,SecurityContextLogoutHandler 将添加为最后一个 LogoutHandler
deleteCookies允许指定退出成功时要删除的 cookie 的名称,这是显式添加 CookieClearingLogoutHandler 的快捷方式

一言以蔽之:默认开启了注销功能,默认以 "/logout" 路劲表示用户注销请求,注销成功后,默认跳转到 "/login?logout" 登录页面,自动清除 session,清除记住我功能的 Cookie,HttpSession 无效。

3、如下所示,前端提供一个用于注销的超链 <li><a href="#" th:href="@{/logout}">注销</a></li> 即可使用注销功能:

  • 43
    点赞
  • 181
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
Spring Security 是一个强大且灵活的认证和授权框架,用于保护 Spring Boot 应用程序的安全性。下面是一个简单的入门指南,帮助你开始使用 Spring Security: 1. 添加 Spring Security 依赖:在你的项目的 `pom.xml` 文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 2. 创建一个 Spring Security 配置类:创建一个类并注解为 `@Configuration`,这个类将用于配置 Spring Security。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/public").permitAll() // 允许访问公共资源 .anyRequest().authenticated() // 其他请求需要认证 .and() .formLogin() // 启用表单登录 .and() .logout() // 启用注销功能 .and() .csrf().disable(); // 禁用 CSRF(跨站请求伪造)保护 } } ``` 在上述示例中,我们配置了一些基本的安全规则。可以自定义更多的规则来满足你的需求,比如配置自定义登录页面、添加用户角色等。 3. 添加用户认证:在上述配置类中,可以添加一个内存用户存储来进行简单的用户认证。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("admin") .password("{noop}password") // 使用 {noop} 前缀表示不加密密码 .roles("ADMIN"); } } ``` 在上述示例中,我们创建了一个用户名为 "admin"、密码为 "password"、角色为 "ADMIN" 的用户。 这只是 Spring Security入门指南,你可以进一步学习如何使用数据库存储用户信息、配置角色权限等。希望这些信息对你有所帮助!如果你有更多问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蚩尤后裔-汪茂雄

芝兰生于深林,不以无人而不芳。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值