Spring Security 安全方案(form表单验证)

当我们创建一个新的web项目时,安全方案是必不可少的,主流的权限框架Spring Security、Apache shiro

本文代码源代码

Apache shiro 和 Spring Security 比较:

权限说明
Apache shiroJava安全框架,可以不依赖Spring 在java 项目中使用
Spring SecuritySpring 家族中的一个安全管理框架,非常容易和Spring整合

本例介绍的是Spring Security的SpringBoot 集成方式

form表单认证流程

通常通过 form 表单提交 Username/Password 验证

请求示例图:
在这里插入图片描述

这是一个安全过滤链 SecurityFilterChain 图解,

1、访问一个没有授权的请求

2、 Spring Security 的 FilterSecurityInterceptor 通过抛出一个 AccessDeniedException 的异常表明请求无效

3、 ExceptionTranslationFilter 捕获到异常,使用重定向到 AuthenticationEntryPoint 配置的登录页,表单认证通常使用 LoginUrlAuthenticationEntryPoint,是一个 AuthenticationEntryPoint 的实例

4、浏览器将请求重定向到登录页

5、反馈一些信息到登录页面

在这里插入图片描述

提交用户名密码

当用户密码被提交时, UsernamePasswordAuthenticationFilter 将对用户和密码进行认证. UsernamePasswordAuthenticationFilter` 继承 AbstractAuthenticationProcessingFilter,

UsernamePasswordAuthenticationFilter 内部工作流程类似如下图

在这里插入图片描述
1、当用户提交用户名密码时, UsernamePasswordAuthenticationFilter 通过从HttpServletRequest 获取 username and password,创建一个Authentication 类型的 UsernamePasswordAuthenticationToken

2、接下来将 UsernamePasswordAuthenticationToken 传递给AuthenticationManager 进行认证,AuthenticationManager如何去获取用户权限,依赖用户信息储存机制:

3、认证失败

  • SecurityContextHolder 删除安全上下文.
  • RememberMeServices.loginFail 被调用
  • AuthenticationFailureHandler 认证失败调用

4、认证成功

  • SessionAuthenticationStrategy 认证session处理
  • Authentication 认证信息设置到当前线程 SecurityContextHolder.
  • RememberMeServices.loginSuccess 调用记住用户.
  • ApplicationEventPublisher 分配成功发布一个事件 InteractiveAuthenticationSuccessEvent.
  • 成功之后处理 AuthenticationSuccessHandler 调用

Spring Security 的安全过滤链中的过滤器,每个过滤器都有各自的功能

在这里插入图片描述

FilterChainProxy   #过滤链代理, 请求会先经过此处,然后依次经过过滤链中的过滤器

LogoutFilter
DefaultLogoutPageGeneratingFilter
UsernamePasswordAuthenticationFilter  # 验证用户密码
FilterSecurityInterceptor   # 决定用户是否有权限访问资源

代码开发:

springboot 使用安全框架非常简单,在 maven 的pom.xml 中引入下面2个依赖,基本就完成了方案引入

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<version>2.1.1.RELEASE</version>
		</dependency>
		
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
			<version>2.1.1.RELEASE</version>
        </dependency>

通过配置文件配置用户和角色

#配置默认权限用户
spring.security.user.name=username
#配置默认权限密码
spring.security.user.password=user
#spring.security.user.roles=ADMIN
#spring.security.user.roles=USER
#
spring.security.user.roles=ADMIN,USER

配置一个资源和角色的映射

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //admin 请求的需要ADMIN角色
        //其他的 只要身份验证通过就可以
        http.authorizeRequests().
                 mvcMatchers("/other/**").permitAll().
                 mvcMatchers("/admin/**").hasRole("ADMIN").
                 mvcMatchers("/user/**").hasRole("USER")
                .anyRequest().authenticated()
                .and()
                .formLogin().and()
                .httpBasic();


    }
}

新建立一个测试的Controller

@RestController
public class IndexController {

    /**
     * 只要登录就可以访问
     * @return
     */
    @RequestMapping(value = {"/index" }, method = RequestMethod.GET)
    public ResponseEntity index(){
        return ResponseEntity.ok().data("Hello,index");
    }

    /**
     * ADMIN 角色就可以访问
     * @return
     */
    @RequestMapping(value = {"/admin" }, method = RequestMethod.GET)
    public ResponseEntity admin(){
        return ResponseEntity.ok().data("Hello,admin");
    }

    /**
     * USER 角色就可以访问
     * @return
     */
    @RequestMapping(value = {"/user" }, method = RequestMethod.GET)
    public ResponseEntity user(){
        return ResponseEntity.ok().data("Hello,user");
    }

    /**
     * 无需权限就可以访问
     * @return
     */
    @RequestMapping(value = {"other" }, method = RequestMethod.GET)
    public ResponseEntity other(){
        return ResponseEntity.ok().data("Hello,other");
    }
}

目前演示的是使用内存的方式进行用户名和角色的设置,后续关系可以放在数据库中

角色CODE资源角色名字
ADMIN/admin/**超级管理员
USER/user/**普通用户

然后就可以访问测试了,访问 http://127.0.0.1:9300/sync/index 会跳转到 http://127.0.0.1:9300/sync/login

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值