一、请求参数名设置

之前的表单信息有一些要求:

1、action属性发送的地址是Security设置的URL

2、发送的请求方式是POST

3、请求的账户信息,也就是表单发送的参数,必须对应的是username & password

原因是因为这个过滤器类:

org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter

和下面的方法:

如果要改变默认的请求参数,可以设置:

package cn.zeal4j.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:55
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
// 登陆请求参数设置
usernameParameter("username").
passwordParameter("password"
).
loginPage("/login.html"). // 设置登陆页面URL路径
loginProcessingUrl("/login.action"). // 设置表单提交URL路径
successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求 httpSecurity.authorizeRequests().
antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭
httpSecurity.csrf().disable();
}
}

二、前后端分离登陆成功页的跳转:

问题的产生:

使用默认successForwardUrl并不能用来跳转到外部地址,也就是跨域访问

例如这样设置成功登陆页进行跳转:

successForwardUrl("http://www.baidu.com")

方法分析:

successForwardUrl方法的实现:

public FormLoginConfigurer<H> successForwardUrl(String forwardUrl) {
this.successHandler(new ForwardAuthenticationSuccessHandler(forwardUrl));
return this;
}

内部是调用了一个成功处理器方法,并且注入了一个跳转授权成功处理器对象,构造参数又是这个要登录的页面URL

跳转授权成功处理器类:

package org.springframework.security.web.authentication;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert; public class ForwardAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private final String forwardUrl; public ForwardAuthenticationSuccessHandler(String forwardUrl) {
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl), () -> {
return "'" + forwardUrl + "' is not a valid forward URL";
});
this.forwardUrl = forwardUrl;
} public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
request.getRequestDispatcher(this.forwardUrl).forward(request, response);
}
}

可以看到下面的这个方法是将URL进行转发处理的,所以像跨域处理的是没有办法解决的

这个处理器类是实现了一个接口:

org.springframework.security.web.authentication.AuthenticationSuccessHandler 

接口的方法:

package org.springframework.security.web.authentication;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication; public interface AuthenticationSuccessHandler {
default void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
this.onAuthenticationSuccess(request, response, authentication);
chain.doFilter(request, response);
} void onAuthenticationSuccess(HttpServletRequest var1, HttpServletResponse var2, Authentication var3) throws IOException, ServletException;
}

也就是说,我们可以通过自己写一个类实现这个接口,单独处理前后端分离的重定向登陆URL

package cn.zeal4j.handler;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 23:48
* 前后端分离url登陆处理 Front and rear separation (FARS)
*/
public class FarsAuthenticationSuccessHandler implements AuthenticationSuccessHandler { private String url; public FarsAuthenticationSuccessHandler(String url) {
this.url = url;
} @Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.sendRedirect(url);
}
// @Override
// public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
//
// }
}

改写登陆成功页面URL的方法:

package cn.zeal4j.configuration;

import cn.zeal4j.handler.FarsAuthenticationSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:55
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
// 登陆请求参数设置
usernameParameter("username").
passwordParameter("password").
loginPage("/login.html"). // 设置登陆页面URL路径
loginProcessingUrl("/login.action"). // 设置表单提交URL路径
// successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
successHandler(new FarsAuthenticationSuccessHandler("https://www.acfun.cn/")). // 使用自定义的重定向登陆

failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求 httpSecurity.authorizeRequests().
antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭
httpSecurity.csrf().disable();
}
}

参数Authentication可以获取登陆账户的信息:

package cn.zeal4j.handler;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 23:48
* 前后端分离url登陆处理 Front and rear separation (FARS)
*/
public class FarsAuthenticationSuccessHandler implements AuthenticationSuccessHandler { private String url; public FarsAuthenticationSuccessHandler(String url) {
this.url = url;
} @Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { Object principal = authentication.getPrincipal();
User user = (User) principal;
Collection<GrantedAuthority> authorities = user.getAuthorities();
System.out.println(user.getUsername());
System.out.println(user.getPassword());
for
(GrantedAuthority authority : authorities) {
System.out.println(authority.getAuthority());
}
httpServletResponse.sendRedirect(url);
} // @Override
// public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
//
// }
}

打印结果:

admin
null
admin
normal

密码输出NULL是因为Security的保护限制?

三、前后端分离登陆失败页的跳转:

有成功页面的跳转,对应的就有失败页面的跳转

public FormLoginConfigurer<H> failureForwardUrl(String forwardUrl) {
this.failureHandler(new ForwardAuthenticationFailureHandler(forwardUrl));
return this;
}

也是同样的方法和类似的对象和相同的注入方式

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
// package org.springframework.security.web.authentication; import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert; public class ForwardAuthenticationFailureHandler implements AuthenticationFailureHandler {
private final String forwardUrl; public ForwardAuthenticationFailureHandler(String forwardUrl) {
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl), () -> {
return "'" + forwardUrl + "' is not a valid forward URL";
});
this.forwardUrl = forwardUrl;
} public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
request.setAttribute("SPRING_SECURITY_LAST_EXCEPTION", exception);
request.getRequestDispatcher(this.forwardUrl).forward(request, response);
}
}

所以要实现跨域跳转,一样是实现上面的接口,除了跳转,该方法还要求携带异常对象

自定义实现类

package cn.zeal4j.handler;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 28 3:44
*/
public class FarsAuthenticationFailureHandler implements AuthenticationFailureHandler { private String url; public FarsAuthenticationFailureHandler(String url) {
this.url = url;
} @Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
// 因为跨域,无法携带异常对象
httpServletResponse.sendRedirect(url);
}
}

更改Security跳转配置:

package cn.zeal4j.configuration;

import cn.zeal4j.handler.FarsAuthenticationFailureHandler;
import cn.zeal4j.handler.FarsAuthenticationSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 21:55
*/
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆
// 登陆请求参数设置
usernameParameter("username").
passwordParameter("password").
loginPage("/login.html"). // 设置登陆页面URL路径
loginProcessingUrl("/login.action"). // 设置表单提交URL路径
// successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求
successHandler(new FarsAuthenticationSuccessHandler("https://www.acfun.cn/")). // 使用自定义的重定向登陆
// failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求
failureHandler(new FarsAuthenticationFailureHandler("/error.html")); // 跨域处理,不需要跳转了
httpSecurity.authorizeRequests().
antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问
antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问
anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭
httpSecurity.csrf().disable();
}
}

登陆控制器的跳转方法就不需要了

package cn.zeal4j.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; /**
* @author Administrator
* @file IntelliJ IDEA Spring-Security-Tutorial
* @create 2020 09 27 22:35
*/ @Controller
public class LoginController { @RequestMapping("main.page")
public String toMainPage() {
return "main"; // 模版内的页面不允许重定向,忘了忘了
} @PostMapping("error.page") // 控制器不支持POST请求跳转解析, 需要控制器跳转 Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported]
public String redirectToErrorPage() {
return "redirect:/error.html"; // 重定向要写/标识 区分模版解析
}
}

【Spring-Security】Re03 认证参数修改与跨域跳转处理的更多相关文章

  1. Spring Security 接口认证鉴权入门实践指南

    目录 前言 SpringBoot 示例 SpringBoot pom.xml SpringBoot application.yml SpringBoot IndexController SpringB ...

  2. 最简单易懂的Spring Security 身份认证流程讲解

    最简单易懂的Spring Security 身份认证流程讲解 导言 相信大伙对Spring Security这个框架又爱又恨,爱它的强大,恨它的繁琐,其实这是一个误区,Spring Security确 ...

  3. Spring Cloud实战 | 第九篇:Spring Cloud整合Spring Security OAuth2认证服务器统一认证自定义异常处理

    本文完整代码下载点击 一. 前言 相信了解过我或者看过我之前的系列文章应该多少知道点我写这些文章包括创建 有来商城youlai-mall 这个项目的目的,想给那些真的想提升自己或者迷茫的人(包括自己- ...

  4. Spring Security 自定义认证逻辑

    Spring Security 自定义认证逻辑 这篇文章的内容基于对Spring Security 认证流程的理解,如果你不了解,可以读一下这篇文章:Spring Security 认证流程 . 分析 ...

  5. 170222、使用Spring Session和Redis解决分布式Session跨域共享问题

    使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...

  6. 使用Spring Session和Redis解决分布式Session跨域共享问题

    http://blog.csdn.net/xlgen157387/article/details/57406162 使用Spring Session和Redis解决分布式Session跨域共享问题

  7. 【基础】Html跨域跳转问题整理

    今天遇到一个问题,是有关 跨域跳转问题,涉及到知识比较基础. 具体问题是:  A站点的 PageA (Post数据)到 B站点的 PageB,PageB接受到后Redirect到B站的 PageC:  ...

  8. 学习Spring Boot:(二十八)Spring Security 权限认证

    前言 主要实现 Spring Security 的安全认证,结合 RESTful API 的风格,使用无状态的环境. 主要实现是通过请求的 URL ,通过过滤器来做不同的授权策略操作,为该请求提供某个 ...

  9. Spring Security 安全认证

    Spring Boot 使用 Mybatis 依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> ...

  10. Spring Security 入门(1-5)Spring Security - 匿名认证

    匿名认证 对于匿名访问的用户,Spring Security 支持为其建立一个匿名的 AnonymousAuthenticationToken 存放在 SecurityContextHolder 中, ...

随机推荐

  1. 记一次 .NET某工控视觉自动化系统 卡死分析

    一:背景 1. 讲故事 今天分享的dump是训练营里一位学员的,从一个啥也不会到现在分析的有模有样,真的是看他成长起来的,调试技术学会了就是真真实实自己的,话不多说,上windbg说话. 二:WinD ...

  2. mongodb常用数据库指令

    通过客户端的命令进入到mongodb服务中 mongo命令进入客户端 show dbs  查看数据库 show tables/show collections 查看集合(查看当前库里面的表) db 查 ...

  3. win10 chrome 百分浏览器 centbrowser 收藏夹栏字体突然变小

    win10 chrome 百分浏览器 centbrowser 收藏夹栏字体突然变小 解决方法: 在"开始" >"设置" >"轻松使用&qu ...

  4. 讯飞有一个可以根据描述文本自动生成PPT的AI接口,有趣

    文档:https://www.xfyun.cn/doc/spark/PPTGeneration.html 价格方面提供了免费1000点的额度,生成一次是10点,正好100次,如果要购买的话最低要购买1 ...

  5. window10 java环境变量配置

    window10 此电脑 右击属性 相关设置 高级系统配置 点击右下的 环境变量 在系统变量中新增JAVA_HOME=D:\Program Files\Java\jdk1.8.0_25 在系统变量中修 ...

  6. Java代码规范equals, for continue

    代码规范equals, for continue 代码规范1 if(v.getPartner().contains("文案")){ } //修改成: if("文案&quo ...

  7. MoneyPrinterPlus:AI自动短视频生成工具,详细使用教程

    MoneyPrinterPlus是一款使用AI大模型技术,一键批量生成各类短视频,自动批量混剪短视频,自动把视频发布到抖音,快手,小红书,视频号上的轻松赚钱工具. 之前有出过一期基本的介绍,但是后台收 ...

  8. uniapp 开发微信小程序 使用微信小程序一键登录

    研究了一天的uniapp开发微信小程序的第一步,登录! 刚开始使用uni.getUserInfo函数No!不行,无法运行,研究文档发现是这个函数被微信小程序团队给禁用了,OK换! 后来换成了uni.g ...

  9. 反模式 DI anti-patterns

    反模式 DI anti-patterns 反模式DI anti-patterns <Dependency Injecttion Prinsciples,Practices, and Patter ...

  10. K8s高可用集群二进制部署-V1.20

    一.前置知识点 1.1 生产环境部署K8s集群的两种方式 kubeadm Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集 ...