当前位置: 首页 > news >正文

spring |Spring Security安全框架 —— 认证流程实现

文章目录

    • 开头
    • 简介
    • 环境搭建
    • 入门使用
      • 1、认证
        • 1、实体类
        • 2、Controller层
        • 3、Service层
          • 3.1、接口
          • 3.2、实现类
          • 3.3、实现类:UserDetailsServiceImpl
        • 4、Mapper层
        • 3、自定义token认证filter
    • 注意事项
    • 小结

开头

  • Spring Security 官方网址:Spring Security官网

开头贴官网,有事找官方!

在这里插入图片描述

简介

介绍的话不多说,就一句:

  • Spring Security 是一个安全管理框架。

    • 一般用于中大型项目。小项目使用shiro,shiro上手简单。
    • 不过,一般是这样。小项目练手用也是相当可以的。

好吧!这是三句话,没跑。

环境搭建

基于SpringBoot3搭建的项目,妥妥好用。

组件SpringBoot2.XSpringBoot3.X
JDKJDK 8、9JDK 17+
JPAJPA2.0+JPA3.0+
ServletServlet 3.1+Servlet 5.0
SpringSpring Framework 5+Spring Framework 6+
GradleGradle 4.xGradle7.3

1、依赖导入

	<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.4</version></parent><!--        spring web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
<!--        spring Security--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!--        mybatis-plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.7</version></dependency><!--    mysql驱动--><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency>

2、配置文件

spring:datasource:url: jdbc:mysql://localhost:3306/dataBase?characterEncoding=utf-8&serverTimezone=Asia/Shanghaiusername: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driver
# mybatisPlus 配置
mybatis-plus:configuration:map-underscore-to-camel-case: true# 日志log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:#      逻辑删除logic-delete-field: delFaglogic-delete-value: 1logic-not-delete-value: 0#      主键自增id-type: auto

入门使用

1、认证

废话不多说,贴个认证流程图:

在这里插入图片描述

1、SpringSecurity Config类


//整点实在的,一整套流程,绝对全面。
@Configuration
@EnableWebSecurity
public class SecurityConfig {@Autowiredprivate AuthenticationTokenFilter tokenFilter;@Autowiredprivate AuthenticationEntryPointImpl authenticationEntryPoint;/*PasswordEncoder是一个用于密码加密的接口,它封装了多种主流的加密方法,它们用于密码的安全存储和校验。但计算开销也相对较大,因此在面对高并发性能要求的大型信息系统时:推荐使用会话、OAuth、Token等短期加密策略来实现系统的信息安全。*/@Beanpublic PasswordEncoder getPasswordEncoder(){return new BCryptPasswordEncoder();}/*负责注册为应用程序提供认证服务的 。*/@Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration config ) throws Exception {return config.getAuthenticationManager();}/*Security Filter是通过FilterChainProxy而不是DelegatingFilterProxy注册进SecurityFilterChain的。	过滤器链,配置*/@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception{http.csrf(csrf -> csrf.disable()); //关闭csrf防护http.authorizeHttpRequests(auth ->auth.requestMatchers("/user/login")//请求路径匹配.permitAll()//放行,不作拦截.anyRequest()//其他请求.authenticated());//认证//        自定义token 认证,用于登录后续请求放行。通过springSecurity上下文判断http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);return http.build();}
1、实体类
//主要就是用:username和 password
@Data
public class SysUser implements Serializable {private static final long serialVersionUID = 662137028719131857L;private Long id;
/*** 用户名*/private String username;
/*** 昵称*/private String nickname;
/*** 密码*/private String password;
/*** 用户类型:0:普通 1:管理员*/private String type;
/*** 账号状态:0:正常 1:停用*/private String status;
/*** 邮箱*/private String email;
/*** 手机号*/private String phoneNumber;
/*** 用户性别(0:男 1:女 2 :匿名)*/private String sex;
/*** 头像*/private String avatar;private Integer isDelete;}
2、Controller层
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate SysUserService userService;@PostMapping("/login")public R login(@RequestBody SysUser user){return userService.login(user);}
}
3、Service层
3.1、接口
public interface SysUserService extends IService<SysUser> {/*** 登录* @param user* @return*/R login(SysUser user);
}
3.2、实现类
@Service
public class SysUserServiceImpl extends ServiceImpl<UserMapper, SysUser> implements SysUserService {@Autowiredprivate AuthenticationManager authenticationManager;@Overridepublic R login(SysUser user) {//重写userDetailsService 处理UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword());Authentication authenticate = authenticationManager.authenticate(authenticationToken);if(Objects.isNull(authenticate)){throw new AppException(AppExceptionMsgEnum.LOGIN_ERROR);}//jwt令牌信息//……LoginUser loginuser = (LoginUser) authenticate.getPrincipal();//自定义返回return  R.success(loginuser.getUser());}
}
3.3、实现类:UserDetailsServiceImpl
  • 用于用户信息认证处理
@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.eq(SysUser::getUsername,username);SysUser userResult = userMapper.selectOne(queryWrapper);if(Objects.isNull(userResult)){throw new AppException(AppExceptionMsgEnum.LOGIN_ERROR);}return new LoginUser(userResult);}
}
4、Mapper层
public interface UserMapper extends BaseMapper<SysUser> {
}
3、自定义token认证filter

@Component
public class AuthenticationTokenFilter extends OncePerRequestFilter {@Autowiredprivate UserMapper userMapper;@Overrideprotected void doFilterInternal(HttpServletRequest request,  HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException, ServletException, IOException {//获取tokenString token = request.getHeader("token");String uri = request.getRequestURI();if(uri.equals("/gate/logout")){filterChain.doFilter(request,response);return;}//放行未携带token 的请求,交由后面拦截器处理if (token == null) {filterChain.doFilter(request,response);return;}//获取用户信息,这里由于没有使用jwt,所以仿制了一下SysUser user = new SysUser();user.setUsername(token);LoginUser loginUser = new LoginUser();loginUser.setUser(user);UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null,null);//存储到SecurityContextHolderSecurityContextHolder.getContext().setAuthentication(authenticationToken);//放行filterChain.doFilter(request,response);}}

注意事项

  1. 认证失败后,会抛出异常。使用全局异常处理器 + 自定义异常 使用。
  • 自定义返回类
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)// 属性为NULL 不序列化
public class R<T> {private int status;//    private boolean success;private String message;private T data;@JSONField(format="yyyy-MM-dd HH:mm:ss")private DateTime time;/*** 正确result* @param data* @param <T>* @return*/public static <T> R<T> success(T data){R<T> r = new R<>();
//        r.success = true;r.status = 200;r.data = data;r.message = "successful";r.time = DateTime.now();return r;}public static <T> R<T> success(String msg ,T data){R<T> r = new R<>();
//        r.success = true;r.status = 200;r.data = data;r.message = msg;r.time = DateTime.now();return r;}/*** 错误result* @param msg* @param status* @param <T>* @return*/public static <T> R<T> error(String msg,int status){R<T> r = new R<>();
//        r.success = false;r.status = status;r.message = msg;r.time = DateTime.now();return r;}/*** 错误result* @param msg* @param <T>* @return*/public static <T> R<T> error(String msg){R<T> r = new R<>();
//        r.success = false;r.message = msg;r.time = DateTime.now();return r;}public static <T> R<T> error(AppExceptionMsgEnum appExceptionMsg){R<T> r = new R<>();
//        r.success = false;r.status = appExceptionMsg.getStatus();r.message = appExceptionMsg.getMsg();r.time = DateTime.now();return r;}}
  • 全局异常处理器
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {@ExceptionHandler(value = BadCredentialsException.class)public static <T> R<T> badCredentialsException(BadCredentialsException e) throws InterruptedException {return R.error(AppExceptionMsgEnum.LOGIN_ERROR);}@ExceptionHandler(value = Exception.class)public static <T> R<T> exceptionHandle(Exception e) throws InterruptedException {if(e instanceof AppException){AppException app = (AppException) e;return R.error(app.getMsg(),app.getStatus());}return R.error(e.toString(),500);}
}
  • 自定义异常
@EqualsAndHashCode(callSuper = true)
@Data
public class AppException extends RuntimeException{private int status;private String msg;public AppException(AppExceptionMsgEnum appExceptionMsgEnum) {this.status = appExceptionMsgEnum.getStatus();this.msg = appExceptionMsgEnum.getMsg();}
}
  • 异常枚举类
public enum AppExceptionMsgEnum {//成功SUCCESS(200,"操作成功"),//失败NEED_LOGIN(401,"需要登录后操作"),NO_OPERATION_AUTH(403,"无权限操作"),USERNAME_EXIST(501,"用户名已存在"),PHONE_NUMBER_EXITS(502,"手机号已存在"),EMAIL_EXIST(503,"邮箱已存在"),REQUIRED_USERNAME(504,"必须填写用户名"),LOGIN_ERROR(505," 用户名或密码错误"),WRONG_PAGE_PARAM(506,"wrong page param"),CONTENT_NOT_NULL(507,"评论内容不能为空"),FILENAME_ERROR(508,"上传文件错误"),ONLY_UPDATE_SELF(509,"只能修改自己的信息"),SERVER_ERROR(500,"SERVER ERROR");private int status;private String msg;AppExceptionMsgEnum(int status, String msg) {this.status = status;this.msg = msg;}public int getStatus() {return status;}public String getMsg() {return msg;}
}

例如:

  • API
  • 支持模型类型

小结

  • SpringSecurity5.7.0之前

    • 常见的 Spring HTTP Security 配置类都会继承一个 WebSecurityConfigureAdapter 类。
  • 从 5.7.0-M2 起,WebSecurityConfigureAdapter 被废弃了,不推荐使用。

    • 组件化开始,更加灵活。
  • 基础认证功能完成。完结撒花!!
    在这里插入图片描述

http://www.lryc.cn/news/459706.html

相关文章:

  • Django+vue自动化测试平台---正式开源!!!
  • 电子电气架构 --- 智能网联汽车未来是什么样子?
  • docker安装elasticsearch(es)+kibana
  • 大厂面试真题-说说redis的雪崩、击穿和穿透
  • 【Spring】获取Cookie和Session(@CookieValue()和@SessionAttribute())
  • 【C++打怪之路Lv8】-- string类
  • 【JS】node.js压缩文件的方式
  • 2024免费mac苹果电脑清理垃圾软件CleanMyMac X4.15.8
  • MPA-SVM多变量回归预测|海洋捕食者优化算法-支持向量机|Matalb
  • 【uni-app】HBuilderX安装uni-ui组件
  • ROS2 通信三大件之动作 -- Action
  • 大数据治理:构建数据驱动的智能决策体系
  • k8s微服务
  • 【Java】Java 的反射机制(一):反射概述
  • Monorepo pnpm 模式管理多个 web 项目
  • 2024年诺贝尔物理学奖颁发给了机器学习与神经网络领域的研究者,看是有点意料之外,其实也在情理之中。
  • 《深入理解 C++策略模式的变体:编程灵活性的新维度》
  • 一起体验AI动手实验,OceanBase 2024 年度发布会精彩预告
  • Download Vmware Fusion (free for person)
  • 【Java数据结构】二叉树
  • 虎牙Android面试题及参考答案
  • C++:错误代码分析<2>
  • 怎么ping网络ip地址通不通
  • 前端新机部署
  • 对比 Babel、SWC 和 Oxc:JavaScript 和 TypeScript 工具的未来
  • MySQL SELECT 查询(三):查询常用函数大全
  • axios 的 get 请求传参数
  • 用C++编写信息管理系统(歌单信息管理)
  • 对层级聚类树进行模块分割,定位基因在哪个模块中
  • 机器学习【金融风险与风口评估及其应用】