Spring Security认证之登录表单配置

news2024/11/16 15:44:40

本文内容来自王松老师的《深入浅出Spring Security》,自己在学习的时候为了加深理解顺手抄录的,有时候还会写一些自己的想法。

自定义登录页面

        文接上篇,这一篇学习如何自定义登录表单。我们创建一个Spring Boot项目之后,还是一样引入Spring Security和Web的基本依赖:

         <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>

        项目创建好之后,我们配置用来登录的用户名和密码:

spring.security.user.name=tlh
spring.security.user.password=123456
spring.security.user.roles=admin,users

        接下来我们我们在resources/static目录下创建有个loging.thml页面。这个就是我们之定义的登录页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
    <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<style>
    #login .container #login-row #login-column #login-box {
        border: 1px solid #9C9C9C;
        background-color: #EAEAEA;
    }
</style>
<body>
<div id="login">
    <div class="container">
        <div id="login-row" class="row justify-content-center align-items-center">
            <div id="login-column" class="col-md-6">
                <div id="login-box" class="col-md-12">
                    <form id="login-form" class="form" action="/doLogin" method="post">
                        <h3 class="text-center text-info">登录</h3>
                        <div class="form-group">
                            <label for="username" class="text-info">用户名:</label><br>
                            <input type="text" name="uname" id="uname" class="form-control">
                        </div>
                        <div class="form-group">
                            <label for="password" class="text-info">密码:</label><br>
                            <input type="text" name="passwd" id="password" class="form-control">
                        </div>
                        <div class="form-group">
                            <input type="submit" name="submit" class="btn btn-info btn-md" value="登录">
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
</body>

        这个login.html中的核心内容就是一个登录表单,登录表单的三个地方需要注意:

  • form的action是/doLogin,表示表单提交到/doLogin接口
  • 用户名的输入框的name属性为uname
  • 用户密码的输入框的name属性为password

        login.html配置好之后我们来定义两个测试接口,作为受保护的资源。等我们登录成功之后我们就可以访问到受保护的资源。接口定义如下:

/**
 * @author tlh
 * @date 2022/11/15 21:25
 */
@RestController
public class HelloController {

    @RequestMapping("/index")
    public String index() {
        return "login success";
    }

    @RequestMapping("/hello")
    public String hello() {
        return "hello spring security";
    }
}

        最后在提供一个Spring Security的配置类:

**
 * @author tlh
 * @date 2022/11/16 21:11
 */
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() //表示开启权限配置
                .anyRequest().authenticated() //表示所有的请求都需要认证之后才能访问
                .and() //返回HttpSecurity对象
                .formLogin()  //采用表单登录的方式认证
                .loginPage("/login.html") //配置登录页面
                .loginProcessingUrl("/doLogin") //配置登录接口
                .defaultSuccessUrl("/index") //登录认证成功之后跳转的地址
                .failureUrl("/login.html")  //登录认证失败的时候跳转的地址
                .usernameParameter("uname")  //登录表单提交时用户名的参数名称
                .passwordParameter("passwd")  //登录表单提交时密码的参数名称
                .permitAll() //表示登录相关的页面接口不做拦截直接通过。
                .and()  //返回HttpSecurity对象
                .csrf().disable();  //禁用CSRF防御机制
    }
}

        这里需要注意的是loginProcessingUrl、usernameParameter、passwordParameter需要和login.html中登录表单的配置一致。

        配置完成之后,我们启动Spring Boot项目,在浏览器中输入:http://localhost:8080/index ,会自动跳转到:http://localhost:8080/login.html 。输入正确的账号和密码就能访问到我们index接口了。

登录成功之后的页面:

         经过上面的配置我们已经自定义了一个登录页面了,用户登录成功之后就能访问受保护的资源了。

详细配置

        前面讲的配置比较粗糙,这里还有一些比较详细的配置我们一起来学习下。登录成功之后,除了defaultSuccessUrl可以实现登录成功之后的跳转之外,successForwardUrl也能实现相同的功能。代码如下:

/**
 * @author tlh
 * @date 2022/11/16 21:11
 */
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/doLogin")
                .successForwardUrl("/index")
                .failureUrl("/login.html")
                .usernameParameter("uname")
                .passwordParameter("passwd")
                .permitAll()
                .and()
                .csrf().disable();
    }
}

        defaultSuccessUrl和successForwardUrl两者不同的地方在于:

  • defaultSuccessUrl表示等用户登录成功之后,会自动重定向到登录之前的地址上去。比如:用户在没有认证登录前访问的是/index,用户会被自动重定向到登录页面,用户输入正确的账号和密码之后又会被重定向到/index地址上。
  • successForwardUrl不会考虑之前的用户访问的什么地址,只要用户登录成功就会通过服务端跳转到successForwardUrl所指定的页面。
  • defaultSuccessUrl还有一个重载的方法,如果第二个参数传入true,就能实现和successForwardUrl相同的效果。即不考虑用户之前访问的地址,只要成功就会重定向到defaultSuccessUrl指定的地址。两者不同的地方在于defaultSuccessUrl是通过重定向试下你的跳转(客户端跳转),而successForwardUrl则是通过服务端实现跳转的。

        无论是defaultSuccessUrl还是successForwardUrl,最终都是通过AuthenticationSuccessHandler的实例来实现的:

public interface AuthenticationSuccessHandler {

	default void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
			Authentication authentication) throws IOException, ServletException {
		onAuthenticationSuccess(request, response, authentication);
		chain.doFilter(request, response);
	}
	
	void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException;
}

        AuthenticationSuccessHandler的默认实现类有三个:ForwardAuthenticationSuccessHandler、SavedRequestAwareAuthenticationSuccessHandler、SimpleUrlAuthenticationSuccessHandler。

        不管是ForwardAuthenticationSuccessHandler还是SavedRequestAwareAuthenticationSuccessHandler或者是SimpleUrlAuthenticationSuccessHandler都是来实现页面跳转的。现在更加流行的是前后端分离的开发模式了,更多时候后端返回的是Json数据。下面我们通过自定义AuthenticationSuccessHandler来实现登录成功之后返回Json字符串。我们发现在配置 defaultSuccessUrl和successForwardUrl的时候其实是间接配置AuthenticationSuccessHandler的实例,那我们就直接自己实现AuthenticationSuccessHandler的实例。代码如下:

/**
 * @author tlh
 * @date 2022/11/16 21:11
 */
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/doLogin")
                .successHandler(getAuthenticationSuccessHandler())
                .failureUrl("/login.html")
                .usernameParameter("uname")
                .passwordParameter("passwd")
                .permitAll()
                .and()
                .csrf().disable();
    }

    AuthenticationSuccessHandler getAuthenticationSuccessHandler() {
        return new AuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                response.setContentType("application/json;charset=utf-8");
                Map<String, String> respMap = new HashMap<>(2);
                respMap.put("code", "200");
                respMap.put("msg", "登录成功");
                ObjectMapper objectMapper = new ObjectMapper();
                String jsonStr = objectMapper.writeValueAsString(respMap);
                response.getWriter().write(jsonStr);
            }
        };
    }
}

        重启项目登录成功之后就能看到服务器返回的Json字符串:

 小结

        上面是登录页面自定义和登录认证成功之后的讲解。其实登录认证失败和登出的逻辑非常类似,有兴趣的小伙伴可以自己看看api来实现。实现关键词:AuthenticationFailureHandler和logoutSuccessHandler

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/12143.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

windows docker 及 k8s 环境搭建

docker 环境搭建 下载 docker 下载 docker for desktop&#xff0c; , 配置 镜像源 开通 kubenates 功能 注册一个 docker hub 账号 记住账号密码&#xff0c; 将来拉取镜像要用到&#xff0c; 在 docker for desktop 中登录该账号 kubenates 环境搭建 docker 中开通 k8…

nginx服务器

一、介绍 Nginx (engine x) 是一个高性能的HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP服务。Nginx是由伊戈尔赛索耶夫为俄罗斯访问量第二的Rambler.ru站点&#xff08;俄文&#xff1a;Рамблер&#xff09;开发的&#xff0c;第一个公开版本0.1.0发布于2…

用户管理系统(2)

2.实现添加功能:有两个和后端交互的接口 根据用户的身份显示登陆界面: 进行插入操作: 1)在我们的前端直接获取到用户名&#xff0c;密码&#xff0c;确认密码&#xff0c;年龄&#xff0c;QQ&#xff0c;邮箱&#xff0c;判断他们是否为空&#xff0c;检测密码和确认密码是否一…

docker 第二次学习笔记

一、dockers简介 docker官网&#xff1a;https://www.docker.com 1.1 docker定义 docker是一种容器化技术&#xff0c;用来更好的构建和发布应用。 二、docker安装 2.1 方法1 centos7.x系统的安装 官网安装步骤&#xff1a;https://docs.docker.com/engine/install/cento…

IDEA中,maven项目下,lombok插件 ,添加lombok.jar, Maven项目下lombok依赖配置

IDEA中&#xff0c;maven项目下&#xff0c;lombok插件 &#xff0c;添加lombok.jar, Maven项目下lombok依赖配置 Maven 项目的创建 在IDEA 21版中&#xff0c;Maven项目无需下载其他版本&#xff0c;查看有无Maven&#xff0c;如果没有下载 安装 首先打开IDEA &#xff0c;点…

​ 详解Linux内核通信-proc文件系统

使用 /proc 文件系统来访问 Linux 内核的内容&#xff0c;这个虚拟文件系统 在内核空间和用户空间之间打开了一个通信窗口&#xff1a; /proc 文件系统是一个虚拟文件系统&#xff0c;通过它可以使用一种新的方法在 Linux内核空间和用户间之间进行通信。在 /proc 文件系统中&…

MySQL事务和索引

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;MySQL &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录索引概念使用索引在MySQL中的数据结构事务概念mysql的隔离级别索引 概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所…

一图看懂,阿里云飞天企业版如何支持政企数智创新

杭州&#xff0c;2022年11月5日 – 今日&#xff0c;在云栖大会专有云技术和应用实践论坛&#xff0c;阿里云重磅发布飞天企业版在建云、管云、用云方面的全面升级&#xff0c;并邀请行业专家、政企客户代表和合作伙伴面向未来十年共话新一代政企IT发展趋势&#xff0c;分享阿里…

行业洞察 | AI贩卖的焦虑,我们该买单吗?

图片来源Midjourney Showcase 在过去的几个月里&#xff0c;人工智能生成的艺术在受欢迎程度和可访问性方面都经历了快速增长。随着DALL-E、Midjourney和Stable Diffusion等引擎刺激了 AI 生成的艺术品在在线平台上的大量涌入。 此前&#xff0c;一位美国39岁游戏设计师&#…

测试行业3年经验,面试想拿 15K,HR说你只值 7K,该如何回答或者反驳?

面试最尴尬的不是被拒绝&#xff0c;而是直接说你不值那个价格... 最近朋友在面试的时候&#xff0c;HR 突然来了句&#xff1a;你只值 7K。朋友后面和我说了这个事。我想如果是我处在这种情况下&#xff0c;自己并不能很好地回答或者反驳。不知道大家会怎么回答或者反驳&…

深入浅出了解MYSQL8特性注入是什么

前言 今天给大家带来的是MYSQL8版本的特性注入&#xff0c;说起SQL注入大家一定不陌生&#xff0c;可是你有没有想过&#xff0c;当SQL注入中最关键的函数SELECT被过滤后&#xff0c;我们要如何去执行SQL语句呢&#xff0c;这就是本文要讲的内容&#xff0c;即利用MYSQL8版本的…

智慧人社解决方案-最新全套文件

智慧人社解决方案-最新全套文件一、建设背景二、思路架构三、建设方案1、全局性数据整合2、综合数据分析平台3、一体化数据管控四、获取 - 智慧人社全套最新解决方案合集一、建设背景 智慧人社平台以建设智慧大社保服务体系为目标&#xff0c;全面践行“互联网&#xff0b;人社…

python基于PHP+MySQL的大学生交友社交网站

近年来,大学生的数量在逐步的增加,为了能够让这些大学生有一个更好的交友环境,需要创建一个基于大学生的社交交友网站。这样可以拉近彼此大学生之间的感情,让他们可以更好的进行学习和交流。 PHP大学生交友社交网站通过PHP&#xff1a;MySQL进行开发,分为前台和后台两部分,通过…

[附源码]SSM计算机毕业设计餐厅卫生安全系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

mariadb10.8 主主同步 相互复制

1. 配置说明 操作系统&#xff1a;CentOS7 CPU指令集&#xff1a;x86_64 host1 主机&#xff1a; 2 core 2G 40GIP&#xff1a;192.168.0.98 host2 主机&#xff1a; 2 core 2G 40GIP&#xff1a;192.168.0.166 2. 数据库安装 见 MariaDB官方下载文档 https://mariadb.or…

mysql“数据不存在插入,存在则更新”实现

参考文章:Mysql:如果数据存在则更新&#xff0c;不存在则插入 场景 工作中有遇到需要配置一些指定的字段数据&#xff0c;但数据量大&#xff0c;不清楚之前是否有配置过&#xff0c;正确的思路应该是如果有这条数据了&#xff0c;那么更新数据的值&#xff0c;如果没有这条数…

股票行情接口level2的盘口信息和level1有哪些区别?

普通的行情接口软件会有价格曲线、五档盘口、分时成交等等这些行情数据&#xff0c;但是股票行情接口level2所能够提供的行情数据远远不止这些&#xff0c;level2顾名思义其实就是level1的高配版&#xff0c;那么它包含的数据相对于比普通行情接口的会更精细也更丰富&#xff0…

华为 x 香格里拉集团|品质网络守护数字旅程

作者 | 曾响铃 文 | 响铃说 酒店行业正在快速推动数字化&#xff0c;其目标是对内提升酒店管理效率&#xff0c;对外提升宾客入住体验&#xff1b;而网络作为整个数字化变革的联接底座&#xff0c;迫切需要进行升级和优化。以香格里拉集团为例&#xff0c;作为成立超过半个世…

微信怎么使用手机号码收款转账?

微信怎么使用手机号码收款&#xff1f; 1、微信手机号码收款方&#xff0c;打开微信钱包&#xff0c;并点击钱包进入&#xff1b; 2、在微信钱包找到支付设置&#xff0c;并点击进入支付设置&#xff1b; 3、在微信钱包支付设置内&#xff0c;开启允许通过手机号向我转账&…

力荐,京东首席架构师:亿级流量架构的核心技术文档免费分享

学习是一种基础性的能力。然而&#xff0c;“吾生也有涯&#xff0c;而知也无涯。”&#xff0c;如果学习不注意方法&#xff0c;则会“以有涯随无涯&#xff0c;殆矣”。 学习就像吃饭睡觉一样&#xff0c;是人的一种本能&#xff0c;人人都有学习的能力。我们在刚出生的时候…