增加一下类

package com.zscq.framework.sms;import org.springframework.security.authentication.AuthenticationProvider;
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;/*** 短信登陆鉴权 Provider,要求实现 AuthenticationProvider 接口** @author gmk*/
public class SmsCodeAuthenticationProvider implements AuthenticationProvider {private UserDetailsService userDetailsService;@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {SmsCodeAuthenticationToken authenticationToken = (SmsCodeAuthenticationToken) authentication;String telephone = (String) authenticationToken.getPrincipal();UserDetails userDetails = userDetailsService.loadUserByUsername(telephone);// 此时鉴权成功后,应当重新 new 一个拥有鉴权的 authenticationResult 返回SmsCodeAuthenticationToken authenticationResult = new SmsCodeAuthenticationToken(userDetails, userDetails.getAuthorities());authenticationResult.setDetails(authenticationToken.getDetails());return authenticationResult;}@Overridepublic boolean supports(Class<?> authentication) {// 判断 authentication 是不是 SmsCodeAuthenticationToken 的子类或子接口return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication);}public UserDetailsService getUserDetailsService() {return userDetailsService;}public void setUserDetailsService(UserDetailsService userDetailsService) {this.userDetailsService = userDetailsService;}
}
package com.zscq.framework.sms;import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;import java.util.Collection;/*** 短信登录 AuthenticationToken,模仿 UsernamePasswordAuthenticationToken 实现** @author gmk*/
public class SmsCodeAuthenticationToken extends AbstractAuthenticationToken {private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;/*** 在 UsernamePasswordAuthenticationToken 中该字段代表登录的用户名,* 在这里就代表登录的手机号码*/private final Object principal;/*** 构建一个没有鉴权的 SmsCodeAuthenticationToken*/public SmsCodeAuthenticationToken(Object principal) {super(null);this.principal = principal;setAuthenticated(false);}/*** 构建拥有鉴权的 SmsCodeAuthenticationToken*/public SmsCodeAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {super(authorities);this.principal = principal;// must use super, as we overridesuper.setAuthenticated(true);}@Overridepublic Object getCredentials() {return null;}@Overridepublic Object getPrincipal() {return this.principal;}@Overridepublic 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();}}
package com.zscq.framework.sms;import com.zscq.common.core.domain.entity.SysUser;
import com.zscq.common.core.domain.model.LoginUser;
import com.zscq.common.enums.UserStatus;
import com.zscq.common.exception.base.BaseException;
import com.zscq.common.utils.StringUtils;
import com.zscq.framework.web.service.SysPermissionService;
import com.zscq.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;/*** 用户验证处理** @author gmk*/
@Service("userDetailsByTelephoneServiceImpl")
public class UserDetailsByTelephoneServiceImpl implements UserDetailsService {private static final Logger log = LoggerFactory.getLogger(UserDetailsByTelephoneServiceImpl.class);@Autowiredprivate ISysUserService userService;@Autowiredprivate SysPermissionService permissionService;@Overridepublic UserDetails loadUserByUsername(String phone) throws UsernameNotFoundException {SysUser user = userService.selectUserByPhonenumber(phone);if (StringUtils.isNull(user)) {log.info("登录用户:{} 不存在.", phone);throw new UsernameNotFoundException("登录用户:" + phone + " 不存在");} else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {log.info("登录用户:{} 已被删除.", phone);throw new BaseException("对不起,您的账号:" + phone + " 已被删除");} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {log.info("登录用户:{} 已被停用.", phone);throw new BaseException("对不起,您的账号:" + phone + " 已停用");}return createLoginUser(user);}public UserDetails createLoginUser(SysUser user) {return new LoginUser(user, permissionService.getMenuPermission(user));}
}
SecurityConfig.java 修改

package com.zscq.framework.config;import com.zscq.framework.sms.SmsCodeAuthenticationProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.filter.CorsFilter;
import com.zscq.framework.config.properties.PermitAllUrlProperties;
import com.zscq.framework.security.filter.JwtAuthenticationTokenFilter;
import com.zscq.framework.security.handle.AuthenticationEntryPointImpl;
import com.zscq.framework.security.handle.LogoutSuccessHandlerImpl;import javax.annotation.Resource;/*** spring security配置* * @author ruoyi*/
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{/*** 自定义用户(账号密码)认证逻辑*/@Autowired@Qualifier("userDetailsServiceImpl")private UserDetailsService userDetailsService;/*** 自定义用户(手机号验证码)认证逻辑*/@Autowired@Qualifier("userDetailsByTelephoneServiceImpl")private UserDetailsService userDetailsServiceByTelephone;/*** 认证失败处理类*/@Autowiredprivate AuthenticationEntryPointImpl unauthorizedHandler;/*** 退出处理类*/@Autowiredprivate LogoutSuccessHandlerImpl logoutSuccessHandler;/*** token认证过滤器*/@Autowiredprivate JwtAuthenticationTokenFilter authenticationTokenFilter;/*** 跨域过滤器*/@Autowiredprivate CorsFilter corsFilter;/*** 允许匿名访问的地址*/@Autowiredprivate PermitAllUrlProperties permitAllUrl;/*** 解决 无法直接注入 AuthenticationManager** @return* @throws Exception*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception{return super.authenticationManagerBean();}/*** anyRequest          |   匹配所有请求路径* access              |   SpringEl表达式结果为true时可以访问* anonymous           |   匿名可以访问* denyAll             |   用户不能访问* fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)* hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问* hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问* hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问* hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问* hasRole             |   如果有参数,参数表示角色,则其角色可以访问* permitAll           |   用户可以任意访问* rememberMe          |   允许通过remember-me登录的用户访问* authenticated       |   用户登录后可访问*/@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception{// 注解标记允许匿名访问的urlExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity.authorizeRequests();permitAllUrl.getUrls().forEach(url -> registry.antMatchers(url).permitAll());SmsCodeAuthenticationProvider smsCodeAuthenticationProvider = new SmsCodeAuthenticationProvider();smsCodeAuthenticationProvider.setUserDetailsService(userDetailsServiceByTelephone);httpSecurity// CSRF禁用,因为不使用session.csrf().disable()// 认证失败处理类.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()// 基于token,所以不需要session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()// 过滤请求.authorizeRequests()// 对于登录login 注册register 验证码captchaImage 短信验证码请求 允许匿名访问.antMatchers("/login","/loginByPhone", "/register", "/captchaImage","/sendSms").anonymous()// 静态资源,可匿名访问.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll().antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated().and().headers().frameOptions().disable();// 添加Logout filterhttpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);// 添加JWT filterhttpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);// 添加CORS filterhttpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class)//手机验证码的provider.authenticationProvider(smsCodeAuthenticationProvider);}/*** 强散列哈希加密实现*/@Beanpublic BCryptPasswordEncoder bCryptPasswordEncoder(){return new BCryptPasswordEncoder();}/*** 身份认证接口*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception{auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());}
}
SysLoginController.java增加 
    /*** 登录方法,手机号登录** @param loginBody 登录信息* @return 结果*/@PostMapping("/loginByPhone")public AjaxResult loginByPhone(@RequestBody LoginBody loginBody){AjaxResult ajax = AjaxResult.success();// 生成令牌String token = loginService.loginByPhone(loginBody.getPhonenumber(),loginBody.getCode(),loginBody.getUuid());ajax.put(Constants.TOKEN, token);return ajax;}
SysLoginService.java增加 
/*** 登录验证** @param phonenumber 手机号* @param code 验证码* @param uuid 唯一标识* @return 结果*/public String loginByPhone(String phonenumber,String code, String uuid){// 校验手机验证码checkMessageCaptcha(code, uuid);/// 用户验证Authentication authentication = null;try {// 该方法会去调用UserDetailsServiceImpl.loadUserByUsernameauthentication = authenticationManager.authenticate(new SmsCodeAuthenticationToken(phonenumber));} catch (Exception e) {if (e instanceof BadCredentialsException) {AsyncManager.me().execute(AsyncFactory.recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));throw new UserPasswordNotMatchException();} else {AsyncManager.me().execute(AsyncFactory.recordLogininfor(phonenumber, Constants.LOGIN_FAIL, e.getMessage()));throw new ServiceException(e.getMessage());}}AsyncManager.me().execute(AsyncFactory.recordLogininfor(phonenumber, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));LoginUser loginUser = (LoginUser) authentication.getPrincipal();// 生成tokenreturn tokenService.createToken(loginUser);}/*** 校验短信验证码* @param code* @param uuid*/private void checkMessageCaptcha(String code, String uuid) {// 校验短信验证码是否正确String verifyKey = CacheConstants.SMS_CODE_KEY + uuid;String captcha = redisCache.getCacheObject(verifyKey);if (!code.equalsIgnoreCase(captcha)){throw new ServiceException("验证码不正确");}}

ruoyi 前后端分离 增加手机号登录相关推荐

  1. Ruo-Yi 前后端分离防止XSS攻击和自定义可以重复读取InputStream流

    Ruo-Yi 前后端分离防止XSS攻击和自定义可以重复读取InputStream流 防止XSS攻击分析 1.什么是xss攻击 ​ **XSS 即(Cross Site Scripting)中文名称为: ...

  2. Ruo-Yi前后端分离的数据过滤

    Ruo-Yi前后端分离的数据过滤 若依官网的介绍:http://doc.ruoyi.vip/ruoyi/document/htsc.html#%E6%95%B0%E6%8D%AE%E6%9D%83%E ...

  3. 前后端分离使用 Token 登录解决方案

    前后端分离使用 Token 登录解决方案:https://juejin.im/post/5b7ea1366fb9a01a0b319612 转载于:https://www.cnblogs.com/byd ...

  4. 利用JWT安全验证(前后端分离,单点登录,分布式微服务)

    JWT官网: https://jwt.io/ JWT(Java版)的github地址:https://github.com/jwtk/jjwt JWT请求流程 用户使用账号和面发出post请求: 服务 ...

  5. ruoyi 多模块部署_若依ruoyi前后端分离版服务器部署

    使用若依前后端分离的Vue+Springboot脚手架,进行编译与在服务器上的部署. 使用IDEA作为IDE. 使用Springboot编译Jar包部署. 前提:需要服务器安装Java环境,Mysql ...

  6. php前后端分离登录,前后端分离下如何登录

    1 Web登录涉及到知识点 1.1 HTTP无状态性HTTP是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的.当然它知道是哪个客户端地址发过来的,但是对于 ...

  7. java通过Excel 模板导出复杂统计类excel文档,在ruoyi前后端分离框架中的应用

    Hello, 大家好! 我是不作死就不会死,智商不在线,但颜值超有品的拆家队大队长 --咖啡汪 一只不是在戏精,就是在戏精路上的极品二哈 前几天刚做了java通过Excel 模板导出复杂统计类exce ...

  8. 前后端分离下微信登录高并发问题

    前后端分离 微信登录 高并发问题 目录 具体描述 成功解决的方案 具体描述 前端发起请求 ->(改进 插入 state: uuid) 后端拉起二维码 -> 用户确认 -> 微信回调 ...

  9. SpringSecurity前后端分离下对登录认证的管理

    本案例基于springboot2.0.4,只说对登录验证的管理,不涉及权限的管理.因为学习新东西一下子太多,很容易乱.        首先添加maven依赖,直接开启springboot自带的spri ...

最新文章

  1. 31个Python实战项目带你学会图像处理
  2. Oracle逻辑空间管理
  3. Java基础—8大数据类型
  4. android 和h5交互,Android中与H5的交互
  5. 关于SimpleDateFormat时间格式化线程安全问题
  6. 【华为云技术分享】云图说 | 华为云AnyStack on BMS解决方案:助力线下虚拟化业务迁移上云
  7. 线性回归的梯度下降和正规方程组求解
  8. 【C/C++】与const有关的指针类型赋值
  9. ES6 数组高频使用方法
  10. 计算机换汉语快捷键,电脑常用快捷键
  11. AWS API Gateway Swagger定义
  12. 中英文翻译、语料库等资料
  13. 《Unix编程艺术》读书笔记(1)
  14. sola病毒批量恢复工具 —— 大一的回忆
  15. 什么模式下不可使用曝光补偿_摄影从零到入门 曝光模式与测光方法详解
  16. 我在国企做软件开发这4年。。
  17. 2023湖北大学考研分析
  18. 监控之美——监控之美-监控系统选型分析及误区探讨
  19. 2021HDU多校第四场5-Didn‘t I Say to Make My Abilities Average in the Next Life?!
  20. 判断任意一个二维数组里是否有鞍点(多个鞍点和单个鞍点均能判断),以及鞍点的输出(c语言)

热门文章

  1. 搭建公司自己的npm私服服务器
  2. 餐讯头条丨2019中华小吃产业发展大会圆满落幕
  3. windows电脑版便签工具用哪个?
  4. springboot之aop切面获取请求
  5. NCCloud OpenAPI扩展开发
  6. div css 下划线text-decoration
  7. web渗透测试----34、DoS和DDoS攻击
  8. 【UE4源代码观察】学习队列模板TQueue
  9. 测试英语口语标准的软件,最客观的英语口语APP亲身测评,这3款软件让你的口语脱颖而出...
  10. 互联网跨界造芯的“菊与刀”