Spring Security多种登录方式
目录
- 不用过滤器(使用json传参方式登录)
- SecurityConfig配置
- 账号密码
- 手机号验证码
- 使用
- 使用过滤器实现(使用form表单传参方式登录)
不用过滤器(使用json传参方式登录)
SecurityConfig配置
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;/*** spring security配置*/
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {/** 认证失败 处理类 */@Autowiredprivate AuthenticationEntryPointImpl unauthorizedHandler;/** 退出 处理类 */@Autowiredprivate LogoutSuccessHandlerImpl logoutSuccessHandler;/** jwt token认证过滤器 */@Autowiredprivate JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;/** 手机验证码 认证器 */@Autowiredprivate CaptchaAuthenticationProvider captchaAuthenticationProvider;/** 账号密码 认证器*/@Autowiredprivate UserNameAuthenticationProvider userNameAuthenticationProvider;/*** 认证管理 AuthenticationManager*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {httpSecurity.csrf().disable().cors().and()// 基于token,所以不需要session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()// 认证失败处理类.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()// 过滤请求.authorizeRequests()// 允许匿名访问.antMatchers(antMatchersAnonymous()).anonymous().antMatchers(HttpMethod.GET, antMatchersPermitAll()).permitAll()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated().and().headers().frameOptions().disable();// 退出处理httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);// 添加JWT filter(必须配置与UsernamePasswordAuthenticationFilter之前)httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);}// 允许匿名访问urlprivate String[] antMatchersAnonymous() {return new String[]{"/login" };}// 不需要任何限制url(静态资源)private String[] antMatchersPermitAll() {return new String[]{"/*.html"};}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 添加认证器// 新增短信验证码验证auth.authenticationProvider(captchaAuthenticationProvider);// 账号密码登录验证auth.authenticationProvider(userNameAuthenticationProvider);}/*** 密码加密规则 强散列哈希加密实现(密码加密算法)*/@Beanpublic BCryptPasswordEncoder bCryptPasswordEncoder() {return new BCryptPasswordEncoder();}
}
账号密码
UserNameAuthenticationProvider 账号密码认证器
import java.util.Collections;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;/*** 用户名密码认证器*/
@Slf4j
@Component
public class UserNameAuthenticationProvider implements AuthenticationProvider {/** 进行账号认证实现 */@Autowiredprivate UserDetailsService userDetailsService;/** 密码加密规则 */@Autowiredprivate PasswordEncoder bCryptPasswordEncoder;@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {long time = System.currentTimeMillis();log.info("用户名/密码 开始登录验证 time:{}", time);String username = authentication.getName();String password = authentication.getCredentials().toString();// 1、去调用自己实现的UserDetailsService,返回UserDetailsUserDetails userDetails = userDetailsService.loadUserByUsername(username);// 2、密码进行检查,这里调用了PasswordEncoder,检查 UserDetails 是否可用。if (Objects.isNull(userDetails) || !bCryptPasswordEncoder.matches(password, userDetails.getPassword())) {throw new BadCredentialsException("账号或密码错误");}// 3、返回经过认证的AuthenticationUsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(userDetails, null, Collections.emptyList());result.setDetails(authentication.getDetails());log.info("用户名/密码 登录验证完成 time:{}, existTime:{}", time, (System.currentTimeMillis() - time));return result;}@Overridepublic boolean supports(Class<?> authentication) {boolean res = UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);log.info("用户名/密码 是否进行登录验证 res:{}", res);return res;}
}
手机号验证码
CaptchaAuthenticationToken 短信验证码认证凭证
import java.util.Collection;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;/*** 短信验证码认证凭证*/
public class CaptchaAuthenticationToken extends AbstractAuthenticationToken {private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;private final Object principal; // 手机号private String captcha; // 验证码/*** 此构造函数用来初始化未授信凭据.** @param principal* @param captcha*/public CaptchaAuthenticationToken(Object principal, String captcha) {super(null);this.principal = principal;this.captcha = captcha;setAuthenticated(false);}/*** 此构造函数用来初始化授信凭据.** @param principal* @param captcha* @param authorities*/public CaptchaAuthenticationToken(Object principal, String captcha, Collection<? extends GrantedAuthority> authorities) {super(authorities);this.principal = principal;this.captcha = captcha;super.setAuthenticated(true);}public Object getCredentials() {return this.captcha;}public Object getPrincipal() {return this.principal;}public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {if (isAuthenticated) {throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");}super.setAuthenticated(false);}@Overridepublic void eraseCredentials() {super.eraseCredentials();captcha = null;}
}
CaptchaAuthenticationProvider 短信验证码认证器
import java.util.Collections;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;/*** 短信验证码认证器*/
@Slf4j
@Component
public class CaptchaAuthenticationProvider implements AuthenticationProvider {@Autowiredprivate UserDetailsService userDetailsService;/** 验证码验证服务 */@Autowiredprivate ICaptchaService captchaService;/*** 进行验证码认证** @param authentication* @return* @throws AuthenticationException*/@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {long time = System.currentTimeMillis();log.info("手机验证码 开始登录验证 time:{}", time);String phone = authentication.getName();String rawCode = authentication.getCredentials().toString();// 1. 手机验证码验证captchaService.validate("admin:account:login:key:", phone, rawCode);// 1.根据手机号获取用户信息UserDetails userDetails = userDetailsService.loadUserByUsername(phone);if (Objects.isNull(userDetails)) {throw new BadCredentialsException("当前手机号不存在");}// 3、返回经过认证的AuthenticationCaptchaAuthenticationToken result = new CaptchaAuthenticationToken(userDetails, null, Collections.emptyList());result.setDetails(authentication.getDetails());log.info("手机验证码 登录验证完成 time:{}, existTime:{}", time, (System.currentTimeMillis() - time));return result;}@Overridepublic boolean supports(Class<?> authentication) {boolean res = CaptchaAuthenticationToken.class.isAssignableFrom(authentication);log.info("手机验证码 是否进行登录验证 res:{}", res);return res;}
}
ICaptchaService
/*** 验证码*/
public interface ICaptchaService {/*** 缓存验证码** @param key 缓存前缀key* @param phone* @param code*/public void setCaptcha(String key, String phone, String code);/*** 验证验证码** @param key 缓存前缀key* @param phone* @param code * CustomException 自定义异常*/public boolean validate(String key, String phone, String code) throws CustomException;}
CaptchaServiceImpl 实现类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** 验证码*/
@Component
public class CaptchaServiceImpl implements ICaptchaService {@Autowiredprivate RedisUtil redisUtil;@Overridepublic void setCaptcha(String key, String phone, String code) {// 有效期5分钟redisUtil.set(key + phone, code, 300);}@Overridepublic boolean validate(String key, String phone, String code) throws CustomException {if (StrUtils.isBlank(phone) || StrUtils.isBlank(code)) {throw new CustomException("验证验证码参数为空", 300);}// 获取缓存数据Object v = redisUtil.get(key + phone);if (null == v) {throw new CustomException("验证码过期,请重新获取", 300);}// 验证是否正确if (!code.equalsIgnoreCase(String.valueOf(v))) {throw new CustomException("验证码错误", 300);}// 验证通过 清除缓存redisUtil.delete(key + phone);return true;}
}
使用
下面为简版登录 具体写法以公司为准
@Slf4j
@RestController
public class LoginController {/*** 用户名密码 登录 * LoginBody 实体字段 (username)用户名, (password)用户密码/验证码, (type)登录类型 1-密码登录, 2-短信验证码登录 默认1*/@PostMapping("/login")public Boolean login(@RequestBody LoginBody loginBody) {loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getType());return true;}
}
LoginService
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;/*** 登录校验方法**/
@Slf4j
@Component
public class SysLoginService {@Resourceprivate AuthenticationManager authenticationManager;/*** 登录验证** @param username 用户名* @param password 密码* @param type 登录类型 1-密码登录, 2-短信验证码登录 默认1* @return 结果*/public String login(String username, String password, Integer type) {// 用户验证Authentication authentication = null;try {if (null == type || type == 1) {// 密码登录authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));} else {// 短信验证码登录authentication = authenticationManager.authenticate(new CaptchaAuthenticationToken(username, password));}} catch (Exception e) {log.error("登录验证异常", e);// 登录异常 自己处理业务逻辑}return null;}
}
使用过滤器实现(使用form表单传参方式登录)
推荐看这篇文章 https://www.felord.cn/captchaAuthenticationFilter.html
主要是自己实现过滤器 过滤器继承AbstractAuthenticationProcessingFilter
Spring Security多种登录方式相关推荐
- Springboot + Spring Security多种登录方式:账号用户名登录+微信网页授权登录
一.概述 实现账号用户名+微信网页授权登录集成在Spring Security的思路,最重要的一点是要实现微信登录通过Spring Security安全框架时,不需要验证账号.密码. 二.准备工作 要 ...
- SpringBoot + Spring Security多种登录方式:账号+微信网页授权登录
一.概述 实现账号用户名+微信网页授权登录集成在Spring Security的思路,最重要的一点是要实现微信登录通过Spring Security安全框架时,不需要验证账号.密码. 二.准备工作 要 ...
- Spring Boot Security 多种登录方式集成配置思路及方法 账号用户名登录+微信网页授权登录
概述 实现账号用户名+微信网页授权登录集成在Spring Security的思路 前情提要 本思路完全抛弃Spring Security的配置式账号密码登录模式,采用完全独立的Filter.Provi ...
- 你有没有遇到要实现多种登录方式的场景丫 一起来看看咯 Spring Security 实现多种登录方式,如常规方式外的邮件、手机验证码登录
你好丫,我是博主宁在春,一起加油吧!!! 不知道, 你在用Spring Security的时候,有没有想过,用它实现多种登录方式勒,这次我的小伙伴就给我提了一些登录方面的需求,需要在原有账号密码登录的 ...
- spring security+jwt 登录认证
spring security+jwt 登录认证 1.综述 2.版本与环境 3.架构 4.数据库认证逻辑图 5.案例 security+jwt 5.1引入依赖 5.2新建工具类 5.2新建组件类 5. ...
- Spring Security自定义登录验证及登录返回结果
Spring Security自定义登录验证及登录返回结果 一.功能描述 二.处理逻辑 简单流程 自定义UserDetails 自定义UserDetailsDAO 自定义UserDetailsServ ...
- spring security导致登录后从https跳转至http解决方案
1. 项目为spring boot项目,由原来的http连接更换为https连接,因项目中配置的了spring security,登录被spring security拦截重定向后会跳转到http 解决 ...
- Spring Security MVC登录注销示例教程
Spring Security MVC登录注销示例教程 今天我们将了解Spring Security Login Example.在阅读这篇文章之前,请先阅读我在"Spring 4 Secu ...
- Spring Security:自定义登录页面
本文来说下Spring Security中如何自定义登录页面 文章目录 准备工作 自定义登录界面 本文小结 准备工作 添加模板引擎 这里使用了thymeleaf模板引擎,在pom.xml进行添加: & ...
最新文章
- android jason动画,Android 动画之Lottie动画使用
- 另一种思考:为什么不选JPA、MyBatis,而选择JDBCTemplate?
- 太阳电池板特性实验_汕头市通风柜厂家报价-广州中增实验室设备
- XML转JSON的javascript代码
- sap实施和开发哪个前景_2021年了!还不知道 SAP顾问的职业前景?
- 【渝粤教育】国家开放大学2018年春季 8634-21TAndroid智能手机编程 参考试题
- 玩客云pc端_玩客云电脑客户端-玩客云pc端下载 v1.4.5.112官方版--pc6下载站
- Hadoop完全分布式安装Kafka
- python 设计模式之装饰器模式 Decorator Pattern
- 最大表示法--环形字符串最大字典序(HDU 5442)
- 【转载】linux环境下大数据网站搬家
- 基于IdentityServer4的单点登录——IdentityServer
- git pull 提示当前不在某个分支上解决办法
- 原子操作:CAS、TAS、TTAS、FAA浅析
- [转帖]*野外生活手册~
- 凸优化理论(一)数学优化问题的分类
- 计算机桌面壁纸怎么保存,电脑桌面背景图片保存路径
- Android 11 : 隐私和安全
- 微信公共号推广技巧、快速涨粉丝的7大技巧总结
- 坑爹的MediaPlayer.isPlaying()
热门文章
- 99%IT人都应该收藏的学习,找资料必备之网站
- 鼎捷易飞7.0、8.0、9.0、9.0.12等各版本下载地址
- 计算机管理usb出现问号,usb里有个问号
- matlab htk tools,基于HTK调用MATLAB的语音识别的研究
- 洛谷 P2534 [AHOI2012]铁盘整理(IDA*(dfs+迭代加深+估值函数))
- ffmpeg简单操作mp3与mp4
- hfss史密斯图_教你如何在天线设计上使用HFSS仿真软件?
- 最新UI易/赞支付系统源码+PHP开发的
- r6220 虚拟服务器,网件r6220设置页面打不开 其实很简单
- Android 使用ViewPager2+ExoPlayer+VideoCache 实现仿抖音视频翻页播放