一、请求参数名设置

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

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. react 高阶函数

    HOC(Higher Order Components)就是一个函数,传给它一个组件,它返回一个新的组件. 高阶组件:就相当于手机壳,通过包装组件,增强组件功能. 实现步骤: 首先创建一个函数 指定函 ...

  2. GO语言 GOLANG 上传微信电子小票图片

    GO语言 GOLANG 上传微信电子小票图片.GO HTTP POST 图片文件.GO 上传图片文件.multipart/form-data.image/jpeg.image/png. GO 环境: ...

  3. work03

    第一题: 1.定义一个包含十个元素的数组.数组元素自己给出 2.遍历打印出数组元素 3.求出数组当中的最小值打印出来 4.求出数组当中的最大值打印出来 5,求数组当中 第二大 值 第二题: 1.定义一 ...

  4. 05-CentOS防火墙

    概述 CentOS中的防火墙有很多,如SELinux.Firewall.TCP Wrappers.iptables/netfilter. 每种防火墙都有各自擅长的地方. 这里主要讲两种:SELinux ...

  5. 【ClickHouse】0:clickhouse学习1之数据引擎(数据库引擎,表引擎)

    ClickHouse提供了大量的数据引擎,分为数据库引擎.表引擎,根据数据特点及使用场景选择合适的引擎至关重要,这里根据资料做一些总结. 数据库引擎官方文档: https://clickhouse.t ...

  6. nuxt3正确使用keepalive页面缓存组件缓存

    最近使用nuxt@3.x版本做SEO优化项目比较多,之前也踩坑过,所以记录一下在 nuxt3 中路由缓存的正确使用方法,本人也之前在GitHub社区中提交过反馈问题,最后是在 3.8.2 版本解决了路 ...

  7. 网易传媒基于 Arctic 的低成本准实时计算实践

    网易传媒大数据实际业务中,存在着大量的准实时计算需求场景,业务方对于数据的实效性要求一般是分钟级:这种场景下,用传统的离线数仓方案不能满足用户在实效性方面的要求,而使用全链路的实时计算方案又会带来较高 ...

  8. WCF异常System.ServiceModel.ProtocolException问题处理

    现象: 最近遇到了WCF 服务无法调用的错误,异常如下. System.ServiceModel.ProtocolException, System.ServiceModel, Version=4.0 ...

  9. 第十节 JMeter基础-初级购物车【接口关联-鉴权】

    声明:本文所记录的仅本次操作学习到的知识点,其中商城IP错误,请自行更改. 背景:商城购物车可以添加数据,也可以删除数据. 思路: 登录后添加购物车,加入成功后查看购物车列表. 购物车列表,随机删除, ...

  10. 数据类型的别名&&随机数_C

    // Code file created by C Code Develop #include "ccd.h" #include "stdio.h" #incl ...