SpringSecurity


最近要学太多东西了,学得太浅容易忘记,所以决定拿个实际项目练手,近期会整理笔记上传

1. Spring Security

进入Spring官网的Security可以看到下面这样一个简介:

Spring Security是一个功能强大且高度可定制的身份认证和访问控制框架,它是用于保护基于Spring的应用程序的实际标准。Spring Security是一个框架,致力于为Java应用程序提供身份认证和授权。与所有Spring项目一样,Spring Security的真正强大之处在于可以轻松扩展以满足自定义要求

特点

  • 全面可扩展的身份认证与授权
  • 防止攻击,跨站请求
  • Servlet API集成
  • 与SpringMVC可选集成

以前我们用拦截器或过滤器来做身份认证和权限等功能,类比Spring Security,其底层是一组过滤器链FilterChain,所以学好基础有助于框架的学习

通过pom.xml的依赖关系知道Spring Security是依赖于AOP的,有切面编程的成分,即不需要修改我们原有的代码

总的来说:Spring Security是提供身份认证与授权功能的框架

2. HelloWorld

Spring Security各版本更新变化挺大的,所以列出使用的版本。笔者使用SpringBoot 2.2.5.RELEASE,也就是 Spring Security 5.2.2.RELEASE

2.1 导包

导入了最基本的依赖

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

2.2 启动项目

直接启动Springboot项目然后打开,就会看到有登录页面了(Spring Security自带的)表示Spring Security运行正常,当然我们什么也没有配置,到这里就是HelloWorl的过程了

3. 身份认证

这里我们新建几个页面,其中index全体人员可以访问,page1-3只有对应权限的人可以访问,admin可以访问所有的页面

3.1 新建配置类SecurityConfig

用注解配置,里面的方法会注释说明

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {  // 使用了适配器模式
    @Override
    // 参数我们使用Http,因为现在我们使用的是http
    // 下面的方式调用可以是链式调用
    // 其中方法做简要解释,其实看英文就大概知道什么意思了
    protected void configure(HttpSecurity http) throws Exception {  
        http.authorizeRequests()  // 表示http要请求授权
                .antMatchers("/").permitAll()  // 匹配地址"/",所有人都可访问
                .antMatchers("/page1**").hasRole("page1VIP")  // 访问对应地址,需要角色"page1VIP"
                .antMatchers("/page2**").hasRole("page2VIP")  // 而角色属于权限和数据库方面知识
                .antMatchers("/page3**").hasRole("page3VIP")
            	.and() // 将上面的配置合并下面的配置
            	.formLogin()  // 打开自带的登录页面
            	.and()
            	.rememberMe() // 记住我功能
        		.and()
                .logout();  // 注销
    }

    @Override
    // 为了简便而不使用数据库,直接在内存构造一些用户数据
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 新版本需要密码编码,因为用户信息写死在代码中会被反编译获取
        auth.inMemoryAuthentication()
            .passwordEncoder(new BCryptPasswordEncoder())  // 添加密码编码
                .withUser("admin")  // 添加用户名
                .password(new BCryptPasswordEncoder().encode("admin")) // 添加用户密码,加了编码
                .roles("page1VIP", "page2VIP","page3VIP")  // 给予权限
                .and()  // 将上面的配置合并下面的配置
            	.withUser("page1")
                .password(new BCryptPasswordEncoder().encode("page1"))
                .roles("page1VIP");
    }
}
  • 没有权限则会自动跳转登录页,登陆后返回刚才的页面
  • 该类需要继承WebSecurityConfigurerAdapter并重写里面的方法才能实现定制配置
  • @EnableWebSecurity表示开启配置类,内部有各种组合注解属于Springboot原理

3.2 认证授权测试

  • 主页谁都可以访问
  • 状态码403表示无权访问
  • 记住我功能是加了cookie(remember)实现
  • 注销即删除了相应的cookie

4. 自定义配置

我们不满足于Security提供的页面及其传参地址,那么就需要自定义

4.1 查看默认配置

.and().formLogin这个是提供默认登录表单的,我们点进去看原码,注意看其上的注释注释注释,这里截取部分

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/**").hasRole("USER")
    .and().formLogin()
	.usernameParameter("username") // default is username,默认的用户名接参name
    .passwordParameter("password) // default is password,默认的密码接参name
	.loginPage("authentication/login") // default is /login with an HTTP get,默认的登录页地址
	.failureUrl("authentication/login?failed") // default is /login?error,默认登录失败跳转地址
	.loginProcessingUrl("/authentication/login/process");// default is /login with an HTTP post
                       // 默认的登录处理url,即传表单的地址
}

看过一个方法的注释,我们就可以举一反三,各个函数都可通过注释来了解其有什么可定制的功能

4.2 修改默认配置

此时可以添加自定义的登录页面和注销提交地址,那么其配置可改成如下

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
        .antMatchers("/").permitAll()
        .antMatchers("/page1**").hasRole("page1VIP")
        .antMatchers("/page2**").hasRole("page2VIP")
        .antMatchers("/page3**").hasRole("page3VIP")

        .and()
        .formLogin()
        .loginPage("/login.html")  // 自定义了一个登录页
        .usernameParameter("user")
        .passwordParameter("pwd")
        .loginProcessingUrl("/login")  // 表单提交的地址

        .and()
        .rememberMe().rememberMeParameter("remember") // 记住我传参名

        .and()
        .logout().logoutUrl("/logout").logoutSuccessUrl("/index.html")   // 注销提交地址和返回页面

        .and().csrf().disable(); // 防止csrf的,不然get、post都不能访问
}

主页和登录页的传参名和提交地址

<!doctype html>
<html lang="en">
<head>
    <title>主页</title>
</head>
<body>
    <a href="/login.html">登录</a>
    <a href="/logout">注销</a>
    <h1>这里是主页</h1>
    <a href="page1.html">page1</a>
    <a href="page2.html">page2</a>
    <a href="page3.html">page3</a>
</body>
</html>


<!doctype html>
<html lang="en">
<head>
    <title>登录页</title>
</head>
<body>
    <h1>自定义的登录页</h1>
    <form action="/login" method="post">
        <input type="text" name="user" placeholder="username">
        <input type="text" name="pwd" placeholder="password">
        <input type="checkbox" name="remember"> 记住我
        <input type="submit" value="提交">
    </form>
</body>
</html>

4.3 自定义测试

至此基本的身份验证和授权功能已经完成配置,算是入门了把,往后会有深入配置的笔记

5. 后期补充

http.authorizeRequests()
.antMatchers("/","/login.html").permitAll()  // 匹配地址"/","/login.html",别忘记登录页要排除
.anyRequest().authenticated()  // 表示登录后,其余地址都能访问

参考 https://docs.spring.io/spring-security/site/docs/5.2.3.RELEASE/reference/htmlsingle/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Dubbo第二篇

    Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题

    晚上没宵夜
  • 如此浅显易懂的零拷贝

    显然,从上面得知本机直接内存的分配不会受到Java堆大小的限制,但这里要注意直接内存也是物理内存的一部分,也受到真实内存的限制,所以当直接内存占用过多时,使Ja...

    晚上没宵夜
  • BitMap

    BitMap也称为位图,其原理和布隆过滤器类似,其基本原理都是使用位数组及其下标来表示某些元素是否存在,其在处理大量数据的排序、查询、去重,以及在用户群做交集和...

    晚上没宵夜
  • Gentoo emerge 使用方法

    当我们谈到(软件)包的时候,我们通常指的是Portage树为Gentoo用户提供的包的名称。Portage树是ebuilds文件的集合,这些文件包含了Porta...

    EltonZheng
  • 手把手教你完成课设作业使用Pandas对海平面温度异常进行分析,小白也能看的懂

    最近咨询课设问题的同学越来越多了,大部分都是用Pandas做数据统计的问题,我就找一个相对比较简单的课设题目讲下解题过程。

    不太灵光的程序员
  • 手写一个解析器

    ? 作者:jolamjiang,腾讯 WXG 前端开发工程师 前言 最近工作中有一些同学在做一些效能工具的时候遇到需要写一门领域相关语言(DSL)及其解析器的...

    腾讯技术工程官方号
  • 实验二 直线DDA生成算法的GDI实现

    理解基本图形元素光栅化的基本原理,掌握一种基本图形元素光栅化算法,利用GDI实现直线光栅化的DDA算法。

    步行者08
  • 使用pt-table-checksum校验MySQL主从复制

    pt-table-checksum是一个基于MySQL数据库主从架构在线数据一致性校验工具。其工作原理在主库上运行, 通过对同步的表在主从段执行checksum...

    Leshami
  • [云计算架构:Dynamics ] 多租户 或多实例 ?

    Dynamics 365(在线)为您提供了隔离Dynamics 365数据和用户访问权限的选项。 对于大多数公司而言,在订阅中添加和使用多个实例可提供正确的功能...

    首席架构师智库
  • 应用程序的通信成本

    应用程序的通信成本 什么是通信 一个程序中两个以上功能相互传递信号或数据叫做通信。 什么是成本 这是是指时间成本与空间成本。 时间就是传递数据所花费的时间。空间...

    netkiller old

扫码关注云+社区

领取腾讯云代金券