栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Security入门基础

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Security入门基础

Spring Security入门基础

文章目录
  • Spring Security入门基础
  • 一,Spring Security的使用
    • 1.1 基本术语
    • 1.2 基本使用
      • 1.2.1 引入依赖
      • 1.2.2 配置文件
      • 1.2.3 测试接口
    • 1.3 过滤器链的15个过滤器
    • 1.4 自定义用户认证 WebSecurityConfigurerAdapter
      • 1.4.1 configure(HttpSecurity http)
      • 1.4.2 configure(AuthenticationManagerBuilder auth)
      • 1.4.3 configure(WebSecurity web)
      • 1.4.4 自定义表单登录

一,Spring Security的使用 1.1 基本术语

SpringSecurity是一个强大的可高度定制的认证和授权框架,对于Spring应用来说它是一套Web安全标准。Spring Security注重于为java应用提供认证和授权功能。

OAuth2是用于授权的行业标准协议,为简化客户端开发提供类特定的授权流。

Resource owner(资源拥有者):拥有该资源的最终用户,有访问资源的账号密码。

Resource server(资源服务器):拥有受保护资源的服务器,如果请求包含正确的访问令牌,可以访问资源。

Client(客户端):访问资源的客户端,会使用访问令牌去获取资源服务器的资源,可以是浏览器,移动设备或者服务器。

Authorization server(授权服务器):用于授权用户的服务器,如果客户端授权通过,发放访问资源服务器的令牌。

四种授权模式:

  • Authorization Code(授权码模式):客户端先将用户导向授权服务器,登陆后获取授权码,然后进行授权,最后根据授权码获取访问令牌。

  • Implicit(简化模式):和授权码模式相比,取消了获取授权码的过程,直接获取访问令牌。

  • Resource Owner Password Credential(密码模式):客户端直接向用户获取用户名和密码,之后向授权服务器获取访问令牌。

  • Client Credential(客户端模式):客户端直接通过客户端授权,从授权服务器获取访问令牌。

1.2 基本使用 1.2.1 引入依赖

新创建模块tools-security,引入依赖:

        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
        
            org.springframework.boot
            spring-boot-starter-security
        
1.2.2 配置文件
server:
  port: 9040

spring:
  application:
    name: tools-security
1.2.3 测试接口
    @RequestMapping("test")
    public String test() {
        return "test";
    }

运行项目,在以下截取的部分日志中,找到 Using generated security password,后面的字符串为原始密码(每次运行结果不同),账号为 user

2021-10-23 15:52:58.472  WARN [tools-security,,] 100588 --- [  restartedMain] o.s.c.s.a.z.ZipkinAutoConfiguration      : Check result of the [RestTemplateSender{http://localhost:9411/api/v2/spans}] contains an error [CheckResult{ok=false, error=org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: [Empty JSON_V2 message]}]
2021-10-23 15:52:59.049  INFO [tools-security,,] 100588 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-10-23 15:52:59.303  INFO [tools-security,,] 100588 --- [  restartedMain] .s.s.UserDetailsServiceAutoConfiguration : 

Using generated security password: 0c731ade-806a-4a8e-83e1-e11044fe0f48


访问 http://localhost:9040/test , 会先跳到默认的登录页面,输入账号(user)密码(0c731ade-806a-4a8e-83e1-e11044fe0f48)即可进行访问到 /test 接口。

1.3 过滤器链的15个过滤器

1. org.springframework.security.web.context.SecurityContextPersistenceFilter

首当其冲的一个过滤器

SecurityContextPersistenceFilter主要是使用SecurityContextRepository在session中保存或更新一个securityContext,并将SecurityContext给以后的过滤器使用,来为后续Filter建立所需的上下文。

2. org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter

此过滤器用于集成SecurityContext到Spring异步执行机制中的WebAsyncManager

3. org.springframework.security.web.header.HeaderWriterFilter

向请求的Header中添加相应的信息,可在http标签内部使用security:headers来控制

4. org.springframework.security.web.csrf.CsrfFilter

csrf又称跨域请求伪造,SpringSecurity会对所有post请求验证是否包含系统生成的CSRF的token信息,如果不包含,则报错。起到防止CSRF攻击的效果。

5. org.springframework.security.web.authentication.logout.LogoutFilter

匹配URL为/logout的请求,实现用户退出,清除认证信息。

6. org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter

认证操作全靠这个过滤器,默认匹配URL为/login且必须为post请求。

7. org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter

如果没有在配置文件中指定认证页面,则由该过滤器生成一个默认认证页面

8. org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter

由此过滤器可以生产一个默认的退出登录页面

9. org.springframework.security.web.authentication.www.BasicAuthenticationFilter

此过滤器会自动解析http请求中头部名字为Authentication,且以Basic 开头的头信息。

10. org.springframework.security.web.savedrequest.RequestCacheAwareFilter

通过HttpSessionRequestCache内部维护了一个RequestCache,用于缓存HttpServletRequest

11. org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter

针对ServletRequest进行了一次包装,使得request具有更加丰富的API

12. org.springframework.security.web.authentication.AnpnymousAuthenticationFilter

当SecurityContextHolder中认证信息为空,则会创建一个匿名用户存入到SecurityContextHolder中。

spring security为了兼容未登录的访问,也走了一套认证流程,只不过是一个匿名的身份。

13. org.springframework.security.web.session.SessionManagementFilter

SecurityContextRepository限制同一用户开启多个回话的数量

14. org.springframework.security.web.access.ExceptionTranslationFilter

异常转移过滤器位于整个SpringSecurityFilterChain的后方,用来转换整个链路中出现的异常。

15. org.springframework.security.web.access.intercept.FilterSecurityinterceptor

获取所配置资源访问的授权信息,根据SecurityContextHolder中存储的用户信息来决定其是否有权限

1.4 自定义用户认证 WebSecurityConfigurerAdapter

前面的做法是使用默认账号user和应用启动时自动生成的密码进行访问认证。但是,每个系统都应该有自己的用户体系,需要自定义用户的登录认证和接口的认证控制,这里就需要对WebSecurityConfiguration进行配置,主要关注三个方法:configure(HttpSecurity http),configure(AuthenticationManagerBuilder auth)和configure(WebSecurity)。

  • HttpSecurity 允许基于选择匹配在资源级配置基于网络的安全性,并声明任何其他网址需要成功验证。也就是对角色的权限——所能访问的路径做出限制。
  • AuthenticationManagerBuilder 用于通过允许AuthenticationProvider容易地添加来建立认证机制。配置的是认证信息 主要配置用户身份和角色信息也就是说用来记录账号,密码,角色信息。
  • WebSecurity 用于影响全局安全性(配置资源,设置调试模式,通过实现自定义防火墙定义拒绝请求)的配置设置。一般用于配置全局的某些通用事物,例如静态资源等。

创建WebSecurityConfiguration.java,继承WebSecurityConfigurerAdapter

@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

}
1.4.1 configure(HttpSecurity http)

HttpSecurity 有重要的两个方法authorizeRequests()和requestMatchers()

authorizeRequests()

授权管理控制的方法

这个方法返回一个expressionUrlAuthorizationConfigurer.expressionInterceptUrlRegistry对象。

authorizeRequests定义那些url需要被保护,那些不需要进行保护,通常出来在配置的第一行。

Security所有的权限控制都基于这个类进行控制。如:

http.authorizeRequests().anyRequest().authenticated()要求所有接口都需要进行权限认证,等同于http.authorizeRequests().antMatchers(" @Configuration public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/403", "/404", "/500").permitAll() // 访问403/404/500时不需要认证 .anyRequest().authenticated() // 其他请求需要认证 .and() .formLogin() // 通过form进行登录 .and() .csrf().disable(); // 关闭跨站请求伪造保护 } }

在以上配置中,我定义了请求为/403,/404和/500的三个接口不需要接受认证,直接放行;然后其他请求都需要认证;然后登录时要使用form方式,同时关闭跨站请求伪造保护。

在配置之前,我已经创建了403/404/500三个页面

@Controller
public class PageController {

    @RequestMapping("403")
    public String accessError() {
        return "403";
    }

    @RequestMapping("404")
    public String notFound() {
        return "404";
    }

    @RequestMapping("500")
    public String serverError() {
        return "500";
    }
    

}

此时,运行项目,访问 /404 接口能正常访问,然后访问 /test 接口时,会跳到Spring Security默认登录页面,输入账号密码后才放行。

1.4.2 configure(AuthenticationManagerBuilder auth)

使用自定义用户密码登录(内存方式)

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()   // 在内存存储用户信息
                .withUser("lmc").password("{noop}123") // 用户名为lmc,密码为123,{noop}表示密码不加密
                .roles("USER");  // 给用户lmc赋予USER角色
    }

spring security默认使用密码是需要加密的,即.password(String)里的密码已经是加密过的字符串,如果在前面加上{noop},就表示非加密的密码

.withUser("lmc").password("{noop}123")
 也可以写成
.passwordEncoder(new BCryptPasswordEncoder()).withUser("lmc").password(new BCryptPasswordEncoder().encode("123"))

注意,在security5.0之前默认加密方式是BC,所以只需要写成

.withUser("lmc").password(new BCryptPasswordEncoder().encode("123"))

就可以,但是5.0后加密方式要自己定义,所以需要使用 passwordEncoder() 方法来定义加密方式,否则会报出以下异常:

There is no PasswordEncoder mapped for the id "null"
1.4.3 configure(WebSecurity web)

配置静态资源,忽略认证

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers("/assets
    }
    .grid-content {
        border-radius: 4px;
        min-height: 36px;
        height: 800px;
    }
    .row-bg {
        padding: 10px 0;
        background-color: #f9fafc;
    }

    .el-card {
        padding: 80px;
        height: 638px;
    }


    
lmc-tools
Copyright © 2021 lmc

定义访问登录页接口:

    
    @RequestMapping("login.html")
    public String login() {
        return "login";
    }

配置类修改:

package com.lmc.security.conf;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;


@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers("/assets/**")
                .antMatchers("/403", "/404", "/500")
                .antMatchers("/login.html");
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()   // 在内存存储用户信息
                .withUser("lmc").password("{noop}123") // 用户名为lmc,密码为123,{noop}表示密码不加密
                .roles("USER");  // 给用户lmc赋予USER角色
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()   // 其他请求需要认证
                .and()
                .formLogin()    // 通过form进行登录
                .loginPage("/login.html")
                .loginProcessingUrl("/login")
                .failureUrl("/500")
                .and()
                .csrf().disable();  // 关闭跨站请求伪造保护
    }
}

此时,访问 http://localhost:9040/test 会跳到 http://localhost:9040/login.html 页面,如果账号密码输入错误,就会跳到失败页面 http://localhost:9040/500 ,自定义登录已完成。

源代码在 gitee上 https://gitee.com/lmchh/lmc-tools, 可供参考

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/357725.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号