springsecurity使用:登录与校验
首先是引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
默认方案:
首次使用这个空项目的时候他会给你一个默认的账号
账号名为user
密码在控制台输出如下图

这时再进入后端会直接弹到一个/login的地址,输入上述账号密码即可查看路由的具体内容,也可以输出/logout退出登录
springsercurity本质是一个过滤器链

在默认案例中UsernamePasswordAuthenticationFilter中会调用UserDetailService接口的InMemoryUserDetailManager获取用户信息 ,后续我们需要修改成在数据库中查询信息而非内存中

自拟方案:
登录
- 自定义登录接口:调用ProviderManager认证,通过则生成jwt,并把用户数据存入redis,自定义UserDetailService,把从内存查数据改成从数据库查
- 自定义service继承UserDetailService
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//查询用户信息
User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUserName, username));
if(Objects.isNull(user)){
throw new RuntimeException("用户名或密码错误");
}
String password = user.getPassword();
//todo 查询权限信息
//封装返回
LoginUser loginUser=new LoginUser();
loginUser.setUser(user);
return loginUser;
} - 实现LoginUser类,继承的UserDetails
public class LoginUser implements UserDetails
- 这里如果进行测试的话,会报错:PasswordEncoder会拿获得的密码和数据库比对,但是要求数据库内的格式为{id}password,根据id去判断加密方式。所以我们写的时候会用BC替换掉这个方法
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
} }注:这里使用了bc加密之后数据库的密码也应在添加时替换成加密后的密码.bc提供了matches()和encode()两种方法
- 添加拦截配置,给登录方法放行一下
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeRequests()
.antMatchers("/user/login").anonymous() //匿名访问:未授权前可以使用,授权之后就不再可以使用
.anyRequest().authenticated(); // 必须要授权才可以使用
} - 登录service
public ResponseResult login(User user) {
//进行用户认证
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
if (Objects.isNull(authenticate)) {
throw new RuntimeException("用户名或密码错误");
}
LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
String id = loginUser.getUser().getId().toString();
String jwt = JwtUtil.createJWT(id);
HashMap<String, String> map = new HashMap<>();
map.put("token", jwt);
redisCache.setCacheObject("login:"+id,loginUser);
return new ResponseResult("登录成功", 200, map);
}
- 自定义service继承UserDetailService
- 校验:获取token后解析获取userid,通过redis获取其中用户数据,并将其存入SecurityContextHolder中
- 配置过滤器
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
RedisCache redisCache;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//获取token并解析
String token = request.getHeader("token");
if (!StringUtils.hasText(token)) {
filterChain.doFilter(request, response);
return;
}
String userId;
try {
Claims claims = JwtUtil.parseJWT(token);
userId = claims.getSubject();
} catch (Exception e) {
throw new RuntimeException(e);
}
//从redis中获取用户信息再存入securityContextHolder
String redisKey = "login:" + userId;
LoginUser loginUser = redisCache.getCacheObject(redisKey);
if(Objects.isNull(loginUser)){
throw new RuntimeException("用户未登录");
}
//todo 权限信息还没写
SecurityContextHolder.getContext().
setAuthentication(new UsernamePasswordAuthenticationToken(loginUser,null,null));
filterChain.doFilter(request, response);
}
} - 添加过滤器
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
- 配置过滤器
为什么要存入信息到SecurityContextHolder中:后续步骤都需要从其中取数据,如果是未认证的状态会导致后面不放行
为什么上述两个位置同样用到了UsernamePasswordAuthenticationToken方法但作用不同:Authentication表示当前访问系统的用户,封装了用户相关信息。
在第一个构造函数中,1.5登录service:我们使用了AuthenticationManager.authenticate()这一方法对数据进行逻辑验证,验证失败则返回结果为null
而第二个构造函数中,2.1配置过滤器:这里手动设置安全信息,此时已经通过安全检查了

//config的一些参数使用案例
.authorizeRequests()
.antMatchers("/user/login").anonymous()//匿名访问,是指在未授权前可以使用,授权后就不能再使用此功能了
.antMatchers("/example").permitAll()//什么状态都可以访问
.anyRequest().authenticated();//授权后才可以访问
springsecurity使用:登录与校验的更多相关文章
- Python3.x:获取登录界面校验码图片
Python3.x:获取登录界面校验码图片 实例代码: # python3 # author lizm # datetime 2018-06-01 18:00:00 # -*- coding: utf ...
- crm 系统项目(一) 登录,注册,校验
crm 系统项目(一) 登录,注册,校验 首先创建一个Django项目,关于配置信息不多说,前面有~ models.py文件下创建需要的表格信息,之后导入数据库 from django.db impo ...
- MVC下用户登录状态校验的问题以及解决方案--------------Action全局过滤器的使用
前言当我们访问某个网站的时候需要检测用户是否已经登录(通过Session是否为null),我们知道在WebForm中可以定义一个BasePage类让他继承System.Web.UI.Page,重写它的 ...
- Spring-Security自定义登录页&inMemoryAuthentication验证
Spring Security是为基于Spring的应用程序提供声明式安全保护的安全性框架.框架下内容比较多,可以做到按照角色权限对请求路径进行限制.今天主要验证自定义登录页,在内存用户存储中进行请求 ...
- SpringSecurity 进行自定义Token校验
背景 Spring Security默认使用「用户名/密码」的方式进行登陆校验,并通过cookie的方式存留登陆信息.在一些定制化场景,比如希望单独使用token串进行部分页面的访问权限控制时,默认方 ...
- SpringSecurity+Token实现权限校验
1.Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配 ...
- access登录窗口校验代码一
Private Sub login_Click()If IsNull(Me.username) ThenMsgBox "请输入用户名!", vbExclamationElseIf ...
- SpringBoot+SpringSecurity之如何forword到登录页面
当我们在项目中引入了SpringSecurity框架进行身份校验的时候,如果某个请求需要用户身份认证,那么SpringSecurity会将用户redirect到登录页面.但是有些时候我们希望是forw ...
- SpringSecurity中的Authentication信息与登录流程
目录 Authentication 登录流程 一.与认证相关的UsernamePasswordAuthenticationFilter 获取用户名和密码 构造UsernamePasswordAuthe ...
- js经典校验之注册与登录校验
平时都专注于后台功能的实现和逻辑需求的分析及数据库方面的设计,很少关注前端的设计,而项目开发过程中专门负责后台是不太可能的事,所以前端我们也需要会用,除了漂亮的首页等其他的交给美工来做,一些功能性的东 ...
随机推荐
- Android 13 - Media框架(3)- MediaPlayer生命周期
关注公众号免费阅读全文,进入音视频开发技术分享群! 上一节了解了MediaPlayer api的使用,这一节就我们将会了解MediaPlayer的生命周期与api使用细节. 1.MediaPlayer ...
- 音视频学习-exceeded mem limit: ActiveHard 50 MB (fatal)
一.现象 ReplayKit2 适配中 UPLOAD进程被系统杀掉 日志中显示原因:exceeded mem limit: ActiveHard 50 MB (fatal) 二.内存占用分析 1)系统 ...
- RTOS入门
RTOS是什么? RTOS是一款操作系统,相当于Windows\Linux 分为ucos FreeRTOS RT-Thread LiteOS 比裸机开发的优势在于,多任务系统,不必串行 临界区 临界区 ...
- Tkinter界面实操
常用opencv-python进行图像处理,有时需要图形用户界面,写个Demo以备不时之需. Tkinter 1. 导入库 由于 Tkinter 是内置到 python 的安装包中.只要安装好 Pyt ...
- 算法金 | Python 中有没有所谓的 main 函数?为什么?
大侠幸会,在下全网同名[算法金] 0 基础转 AI 上岸,多个算法赛 Top [日更万日,让更多人享受智能乐趣] 定义和背景 在讨论Python为何没有像C或Java那样的明确的main函数之前,让 ...
- RHCSA认证学习_尝试
第一天 一,linux系统的基本概念以及命令终端字段含义介绍 linux系统的基本概念: ·多用户的系统:允许同时执行多个任务 ·多任务的系统:允许同时执行多个任务 ·严格区分大小写:命令,选项,参数 ...
- echarts做饼图
今天记录下echarts做饼图 父组件 <el-card style="height:600px ;margin-top:20px" v-loading="card ...
- css3 浏览器前缀 线型渐变 过渡属性
css3:没有形成正式版 每个浏览器商,为了能对css3属性形成一个更好的支持,浏览器形成自己一套语法规范,一些css属性,如果想在浏览器上形成支持,有时候需要添加浏览器前缀 谷歌前缀:-webkit ...
- INFINI Labs 产品更新 | 发布 Easysearch Java 客户端,Console 支持 SQL 查询等功能
近年来,日志管理平台越来越流行.使用日志管理平台可以实时地.统一地.方便地管理和查看日志,挖掘日志数据价值,驱动运维.运营,提升服务管理效率. 方案架构 Beats 是轻量级采集器,包括 Filebe ...
- C#.NET 国密 SM2 公钥证书从文本转换
先前的 Util 是直接从文件中转换的 https://www.cnblogs.com/runliuv/p/15079404.html public static AsymmetricKeyParam ...