SpringBoot20 集成SpringSecurity02 -> 利用SpringSecurity进行前后端分离的登录验证
1 SpirngBoot环境搭建
创建一个SpringBoot项目即可,详情参见三少的相关博文
2 引入SpirngSecurity依赖
技巧01:引入了springSecurity相关依赖后,项目就会被SpringSecurity进行管理了;默认的登录名为user,登录密码会被打印到控制台上
技巧02:SpringSecurity默认的配置使用的是
<!--spring-security相关-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.1 启动项目
技巧01:每次启动项目所打印出来的密码都是不一样的
控制台打印的登录密码信息如下:

2.2 请求一个后台实现的RestfulAPI
技巧01:项目启动后,前台首次访问时都会被重定向到一个默认的登录页面
技巧02:springSecurity默认的配置时使用表单进行登录
技巧03:前后端分离时也是使用表单登录,而且表单的用户名必须是username,密码必须是password(PS: 前后端分离时只需要模拟出表单提交请求即可,即:请求路径对应,请求参数和后台对应即可)

2.3 录入信息
技巧01:如果用户名不是user或者密码不是控制台打印的信息,都不会通过验证
技巧02:如果登录信息成功后,SpringSecurity会默认重定向到之前访问的路径
技巧03:前后端分离时要求登录验证无论成功与否都是返回JSON格式的数据,具体怎么跳转有前端进行控制

3 SpirngSecurity基础配置
技巧01:自定义SpringSecurity时需要重写一个UserDetaiService类,而该类需要使用一个对密码进行加密和解密的工具类,所以我们需要在自定义的SpringSecurity配置文件中指定这个密码加密解密工具的类的Bean,使得这个类会被Spring容器管理
package cn.test.demo.base_demo.config.springSecurity; import org.springframework.beans.factory.annotation.Autowired;
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 王杨帅
* @create 2018-05-27 21:27
* @desc
**/
@Configuration
public class FurySpringSecurityConfig extends WebSecurityConfigurerAdapter { /** 依赖注入自定义的登录成功处理器 */
@Autowired
private FuryAuthenticationSuccessHandler furyAuthenticationSuccessHandler; /** 依赖注入自定义的登录失败处理器 */
@Autowired
private FuryAuthenticationFailureHandler furyAuthenticationFailureHandler; // 向spring容器中创建一个Bean
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
} // @Override
// protected void configure(HttpSecurity http) throws Exception {
// http.formLogin()
// .loginProcessingUrl("/login")
// .successHandler(furyAuthenticationSuccessHandler)
// .failureHandler(furyAuthenticationFailureHandler)
// .and().authorizeRequests()
// .antMatchers("/login").permitAll()
// .anyRequest()
// .authenticated()
// .and().csrf().disable();
// }
}
4 继承UserDetaiService
继承UserDetaiService的子类可以实现登录用户验证以及登录用户的权限查询
package cn.test.demo.base_demo.config.springSecurity; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component; /**
* @author 王杨帅
* @create 2018-05-27 21:23
* @desc
**/
@Component
@Slf4j
public class FuryUserDetailService implements UserDetailsService { /**
* 依赖注入密码加密解密工具(PS: 需要在springsecurity的配置文件中配置这个Bean)
*/
@Autowired
private PasswordEncoder passwordEncoder; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 打印前端传过来的用户数据
log.info("前端闯过来的用户名为:{}", username); // 模拟数据库中的数据
String pwd = passwordEncoder.encode("111"); // 返回一个User对象(技巧01:这个User对象的密码是从数据库中取出来的密码)
// // 技巧02:数据库中的密码是在创建用户时将用户的密码利用SpreingSecurity配置中相同的密码加密解密工具加密过的
return new User(username, pwd, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
4.1 测试
重启项目后,访问一个RestfulAPI时;控制台就不会再打印出密码信息了,继承UserDetaiService的子类会接收到前端传过来的用户名和密码,我们可以在继承UserDetaiService的子类中依赖注入先关的持久层来通过用户名到数据库中去查询用户密码,在将查到的密码和用户登录时的密码进行比对,从而判断用户登录验证是否成功;还可以根据用户名到数据库中去查询该用户的权限信息
技巧01:此时用户名可以随便输入
技巧02:由于密码是三少在后台进行硬编码的的,所以登录时密码必须是 “111”(即:用户名任意,密码只要是 111 就可以登录成功,否则就会登录失败)
6 前后端分离配置
需求01:修改表单的登录路径
》配置登录请求路径即可
需求01:无论登录验证成功与否都返回JSON格式字符串
技巧01:以上的需求都可以在自定义的SpringSecurity配置中实现
技巧02:前后端分离时,请求的方式必须是POST方式,而且必须传递username和password两个变量到后台
6.1 验证后的JSON格式返回
只需要分别实现两个处理接口即可:AuthenticationSuccessHandler、AuthenticationFailureHandler;这两个接口分别处理登录验证成功和失败
package cn.test.demo.base_demo.config.springSecurity; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; /**
* @author 王杨帅
* @create 2018-05-27 21:48
* @desc
**/
@Slf4j
@Component
public class FuryAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Autowired
private ObjectMapper objectMapper; // Json转化工具 @Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
log.info("登录验证成功");
response.setContentType("application/json;charset=UTF-8"); // 响应类型
response.getWriter().write(objectMapper.writeValueAsString("登录验证成功"));
}
}
FuryAuthenticationSuccessHandler.java
package cn.test.demo.base_demo.config.springSecurity; import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; /**
* @author 王杨帅
* @create 2018-05-27 21:55
* @desc
**/
@Component
@Slf4j
public class FuryAuthenticationFailureHandler implements AuthenticationFailureHandler { @Autowired
private ObjectMapper objectMapper; @Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
log.info("登录验证失败");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(objectMapper.writeValueAsString(exception));;
}
}
FuryAuthenticationFailureHandler.java
6.2 配置自定SpringSecurity配置
package cn.test.demo.base_demo.config.springSecurity; import org.springframework.beans.factory.annotation.Autowired;
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 王杨帅
* @create 2018-05-27 21:27
* @desc
**/
@Configuration
public class FurySpringSecurityConfig extends WebSecurityConfigurerAdapter { /** 依赖注入自定义的登录成功处理器 */
@Autowired
private FuryAuthenticationSuccessHandler furyAuthenticationSuccessHandler; /** 依赖注入自定义的登录失败处理器 */
@Autowired
private FuryAuthenticationFailureHandler furyAuthenticationFailureHandler; // 向spring容器中创建一个Bean
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginProcessingUrl("/furyLogin") // 登录请求路径
.successHandler(furyAuthenticationSuccessHandler) // 验证成功处理器
.failureHandler(furyAuthenticationFailureHandler) // 验证失败处理器
.and().authorizeRequests()
.antMatchers("/furyLogin").permitAll() // 登录请求路径不进行过滤
.anyRequest()
.authenticated()
.and().csrf().disable(); // 取消跨站请求伪造防护
} }
6.3 测试
利用postman进行测试
技巧01:只需要模拟出 登录请求即可;POST请求,参数分别是username和password
坑01:虽然在springSecurity的自定义配置文件中配置的登录请求路径是 /furyLogin ,但是我们在模拟的时候必须模拟 http://127.0.0.1:9999/dev/furyLogin,因为必须加上IP、端口和应用上下文路径
6.3.1 登录验证失败的效果展示

6.3.2 登录成功的效果

7 利用Angular实现前端登录
8 登录成功后返回对应的菜单信息
9 权限问题
·下面是我的公众号二维码,欢迎关注·
尋渝記

微信号:xyj_fury
SpringBoot20 集成SpringSecurity02 -> 利用SpringSecurity进行前后端分离的登录验证的更多相关文章
- Django 利用JWT实现前后端分离的Token验证
一.什么是Token? Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器会生成一个Token并将此Token返回给客户端,以后客户端只需带上这个Token前来请 ...
- 【SpringSecurity系列2】基于SpringSecurity实现前后端分离无状态Rest API的权限控制原理分析
源码传送门: https://github.com/ningzuoxin/zxning-springsecurity-demos/tree/master/01-springsecurity-state ...
- SpringSecurity04 利用JPA和SpringSecurity实现前后端分离的认证和授权
1 环境搭建 1.1 环境说明 JDK:1.8 MAVEN:3.5 SpringBoot:2.0.4 SpringSecurity:5.0.7 IDEA:2017.02旗舰版 1.2 环境搭建 创建一 ...
- 【SpringSecurity系列3】基于Spring Webflux集成SpringSecurity实现前后端分离无状态Rest API的权限控制
源码传送门: https://github.com/ningzuoxin/zxning-springsecurity-demos/tree/master/02-springsecurity-state ...
- 利用gulp解决前后端分离的header/footer引入问题
在我们进行前后端完全分离的时候,有一个问题一直是挺头疼的,那就是公共header和footer的引入.在传统利用后端渲染的情况下,我们可以把header.footer写成两个单独的模板,然后用后端语言 ...
- Spring-Gateway与Spring-Security在前后端分离项目中的实践
前言 网上貌似webflux这一套的SpringSecurity操作资料貌似很少. 自己研究了一波,记录下来做一点备忘,如果能帮到也在迷惑的人一点点,就更好了. 新项目是前后端分离的项目,前台vue, ...
- 【SpringSecurity系列1】基于SpringSecurity实现前后端分离无状态Rest API的权限控制
源码传送门: https://github.com/ningzuoxin/zxning-springsecurity-demos/tree/master/01-springsecurity-state ...
- 利用CORS解决前后端分离的跨域资源问题
CORS 即CrossOrigin Resources Sharing-跨域资源共享,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求.它是一个妥协,有更大的灵活性,但比起简单地允许所有这些 ...
- springsecurity实现前后端分离之jwt-资料收集
https://www.jianshu.com/p/5b9f1f4de88d https://www.jianshu.com/p/725d32ab92f8 https://blog.csdn.net/ ...
随机推荐
- (三十七)js改变this指向的方法
最近又遇到了JacvaScript中的call()方法和apply()方法,而在某些时候这两个方法还确实是十分重要的,那么就让我总结这两个方法的使用和区别吧. 1.改变函数内部的this指向的三种方法 ...
- HihoCoder 1053 : 居民迁移 二分+贪心+双指针(好题)
居民迁移 时间限制:3000ms 单点时限:1000ms 内存限制:256MB 描述 公元2411年,人类开始在地球以外的行星建立居住点.在第1326号殖民星上,N个居住点分布在一条直线上.为了方便描 ...
- ehchache和redis
Ehcache 在java项目广泛的使用.它是一个开源的.设计于提高在数据从RDBMS中取出来的高花费.高延迟采取的一种缓存方案.正因为Ehcache具有健壮性(基于java开发).被认证(具有apa ...
- BZOJ5337 [TJOI2018]str
题意 小豆参加了生物实验室.在实验室里,他主要研究蛋臼质.他现在研究的蛋臼质是由k个氨基酸按一定顺序构成的.每一个氨基酸都可能有a种碱基序 列si_j 构成.现在小豆有一个碱基串s,小豆想知道在这个碱 ...
- Git 的 cherry-pick 功能
简而言之,cherry-pick就是从不同的分支中捡出一个单独的commit,并把它和你当前的分支合并.如果你以并行方式在处理两个或以上分支,你可能会发现一个在全部分支中都有的bug.如果你在一个分支 ...
- mybatis参数
分是不是用@Param注解的这两种情况, 1,使用@Param注解,就不用理parameterType xml文档直接用 字符串的值,若是一个类,class.property 2, 不使用@Param ...
- Linux 简单字符设备驱动
1.hello_drv.c (1) 初始化和卸载函数的格式是固定的,函数名自定义 (2) printk是内核的打印函数,用法与printf一致 (3) MODULE_LICENSE:模块代码支持开源协 ...
- EditText动态转换只读/编辑状态
public class MyActivity extends Activity { private KeyListener listener; private EditText editText; ...
- java代码练习======每隔5行打印数字
总结:当我们感觉数字排列横排,竖排不好看的时候,学会空几行在排列,哎呦,效果不错喔 package com.aa; public class West2 { public static void ma ...
- PHP实现日志写入log.txt
引言:有时候调试,看不到效果,需要通过写入文件来实现. 案例: <?php $myfile = fopen("log.txt", "a+") or die ...