阶段十-springsecurity总结

jwt认证流程

SpringSecurity 认证过程

 

 

第一步:

创建一个类实现UserDetailsService接口,重写其中的方法

通过重写 public UserDetails loadUserByUsername(String username) 方法

从数据库校验用户输入的用户名

配置SecurityConfig

@Bean注入  PasswordEncoder  通过BCryptPasswordEncoder();

@Bean注入 DaoAuthenticationProvider

设置setUserDetailsService(userDetailsService); 走我们的UsersDetailsService

setPasswordEncoder(passwordEncoder());走我们注入的密码加密器

第二步:

注入过滤器链 SecurityFilterChain

注入过滤器链忽略资源 WebSecurityCustomizer

@Configuration
public class SecurityConfig {
    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    //注入UserDetailsService
    @Bean
    public DaoAuthenticationProvider authenticationProvider(){
        DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
        auth.setUserDetailsService(userDetailsService);
        auth.setPasswordEncoder(passwordEncoder());
        return auth;
    }
    //注入认证管理器
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
    //注入过滤连
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        //关闭csrf攻击防护
        http.csrf().disable();
        //配置认证请求,所有请求都需要过滤
        http.authorizeRequests().anyRequest().authenticated();
        //关闭session会话
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        return http.build();
    }
    //注入过滤链忽略资源
    @Bean
    public WebSecurityCustomizer securityCustomizer() throws Exception{
        return (web )->{
            web.ignoring().antMatchers("/user/login");
        };
    }
}

第三步:

登录实现类

 //认证管理器完成认证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(),user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("用户名或密码错误");
        }
        //使用userid生成token
        User loginUser = (User) authenticate.getPrincipal();
        String userId = loginUser.getId().toString();
        String token = jwtUtils.generateToken(userId);
        //authenticate存入redis
        stringRedisTemplate.opsForValue().set("login:"+userId, JSON.toJSONString(loginUser));
        //把token响应给前端
        HashMap<String,String> map = new HashMap<>();
        map.put("token",token);
        return new ResponseResult(200,"登陆成功",map);

第四步:

自己定义认证管理器jwtAuthenticationTokenFilter

最后把读取到的数据存入本地线程中

为什么放行,因为放行之后有人处理

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private JwtUtils jwtUtils;
    @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;
        }
        //解析token
        String userId;
        try {
            userId = jwtUtils.getUserIdFromToken(token);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("token非法");
        }
        //从redis中获取用户信息
        String redisKey = "login:" + userId;
        String json = stringRedisTemplate.opsForValue().get(redisKey);
        User loginUser = JSONObject.parseObject(json, User.class);
        if (Objects.isNull(loginUser)) {
            throw new RuntimeException("用户未登录");
        }
        //将用户信息存入SecurityContextHolder中
        //TODO 获取权限信息封装到Authenication中
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser,null,null);
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        //放行
        filterChain.doFilter(request,response);
    }
}

把我们的过滤器放入过滤器链

//配置认证过滤器
        http.addFilterAfter(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

因为jwtAuthenticationTokenFilter继承OncePerRequestFilter

为防止SpringBoot的FilterRegistrationBean执行OncePerRequestFilter过滤器

@Configuration
public class WebConfig {
    @Bean
    public FilterRegistrationBean filterRegistrationBean(JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter){
        FilterRegistrationBean<Filter> filterFilterRegistrationBean = new FilterRegistrationBean<>(jwtAuthenticationTokenFilter);
        filterFilterRegistrationBean.setEnabled(false);
        return filterFilterRegistrationBean;
    }
}

第五步:退出登录

从本地线程中获取数据,直接删除,最彻底的是前后端都删除

授权

在springsecurity配置类中开启注解

@EnableWebSecurity //开启springSecurity框架
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启权限注解开发

在controller上配置权限注解

例如:

@PreAuthorize("hasAuthority('test')")
封装权限信息

注意实体类中的权限信息,两个集合

 /*
     * 用户拥有权限
     * */
    @TableField(exist = false)
    private Collection<String> menus;

    @Override
    @JSONField(serialize = false)
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> collection = new ArrayList();
        for (String str : menus){
            SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(str);
            collection.add(simpleGrantedAuthority);
        }
        return collection;
    }

在UserDetailServiceImpl中加入权限,从数据库中获取(多表连接),这里是写死的

//返回user自动会和前台接收的密码比对,这里不用比对密码
        Collection<String> collection = new ArrayList<>();
        collection.add("test");
        user.setMenus(collection);
        return user;

认证过滤器解析权限数据也加入权限信息

//将用户信息存入SecurityContextHolder中
        // 获取权限信息封装到Authenication中
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());

自定义失败处理

如果是认证过程中出现的异常会被封装成AuthenticationException然后调用AuthenticationEntryPoint对象的方法去进行异常处理。

如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。

在SpringSecurity配置信息中注入

    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private AccessDeniedHandler accessDeniedHandler;
 http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).
                accessDeniedHandler(accessDeniedHandler);

跨域问题解决

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 设置允许跨域的路径
        registry.addMapping("/**")
                // 设置允许跨域请求的域名
                .allowedOrigins("*")
                // 是否允许cookie
                .allowCredentials(true)
                // 设置允许的请求方式
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 设置允许的header属性
                .allowedHeaders("*")
                // 跨域允许时间
                .maxAge(3600);
    }
}

开启SpringSecurity的跨域访问

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        ...
        //允许跨域
        http.cors();
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/259702.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++题目速刷】二分查找

【C题目速刷】二分查找 一、二分查找1、题目链接2、解题3、代码 二、在排序数组中查找元素的第一个和最后一个位置1、题目链接2、解题3、代码4、算法模板 三、x的平方根1、解题链接2、解题3、代码 四、搜索插入位置1、题目链接2、解题3、代码 五、山脉数组的峰顶索引1、题目链接…

论文解读:On the Integration of Self-Attention and Convolution

自注意力机制与卷积结合&#xff1a;On the Integration of Self-Attention and Convolution(CVPR2022) 引言 1&#xff1a;卷积可以接受比较大的图片的&#xff0c;但自注意力机制如果图片特别大的话&#xff0c;运算规模会特别大&#xff0c;即上图中右边(卷积)会算得比较快…

虾皮电商申请:一站式开店指南

随着跨境电商的快速发展&#xff0c;越来越多的商家开始意识到东南亚市场的潜力。虾皮电商&#xff08;Shopee&#xff09;作为东南亚地区最大的电商平台之一&#xff0c;为商家提供了一个开拓市场的机会。本文将详细介绍如何在虾皮电商平台上开店&#xff0c;并给出一些建议来…

Kioptrix-1

信息收集 # nmap -sn 192.168.1.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2023-12-18 20:02 CST Nmap scan report for 192.168.1.1 (192.168.1.1) Host is up (0.00025s latency). MAC Address: 00:50:56:C0:00:08 (VMware) Nmap scan report for 0bc…

听GPT 讲Rust源代码--src/tools(17)

File: rust/src/tools/rust-analyzer/crates/profile/src/hprof.rs 在Rust源代码中&#xff0c;rust/src/tools/rust-analyzer/crates/profile/src/hprof.rs文件是rust-analyzer中的性能分析模块&#xff0c;用于代码运行时的性能统计和分析。下面将详细介绍每个结构体的作用&a…

基于DSP的IIR数字滤波器(论文+源码)

1.系统设计 在本次基于DSP的IIR数字低通滤波计中&#xff0c;拟以TMS320F28335来作为系统的主控制器&#xff0c;通过ADC0832模数转换芯片来对输入信号进行采集&#xff1b;通过TLC5615来将低通滤波后的信号进行输出&#xff1b;同时结合MATLAB仿真软件&#xff0c;对设计的II…

2023美团商家信息

2023美团商家电话、地址、经纬度、评分、均价、执照...

排序算法——快排

快速排序算法最早是由图灵奖获得者Tony Hoare设计出来的,他在形式化方法理论以 及ALGOL.60编程语言的发明中都有卓越的贡献,是20世纪最伟大的计算机科学家之—。 而这快速排序算法只是他众多贡献中的—个小发明而已。 快速排序&#xff08;Quick Sort&#xff09;的基本算法思…

SpringBoot3知识总结

SpringBoot3 1、简介 1. 前置知识 Java17Spring、SpringMVC、MyBatisMaven、IDEA 2. 环境要求 环境&工具版本&#xff08;or later&#xff09;SpringBoot3.0.5IDEA2022Java17Maven3.5 3. SpringBoot是什么 Spring Boot是Spring项目中的一个子工程&#xff0c;与我们…

四、Spring IoC实践和应用(基于XML配置方式组件管理)

本章概要 基于XML配置方式组件管理 实验一&#xff1a; 组件&#xff08;Bean&#xff09;信息声明配置&#xff08;IoC&#xff09;实验二&#xff1a; 组件&#xff08;Bean&#xff09;依赖注入配置&#xff08;DI&#xff09;实验三&#xff1a; IoC 容器创建和使用实验四…

Hive参数操作和运行方式

Hive参数操作和运行方式 1、Hive参数操作 1、hive参数介绍 ​ hive当中的参数、变量都是以命名空间开头的&#xff0c;详情如下表所示&#xff1a; 命名空间读写权限含义hiveconf可读写hive-site.xml当中的各配置变量例&#xff1a;hive --hiveconf hive.cli.print.headert…

基于SpringBoot+Vue的小区物业管理系统

基于SpringBootVue的小区物业管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootVue工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 房屋类型 论坛 登录界面 管理员界面 员工界面 摘要 小区物业管理系统是一个…

CTF-PWN-堆-【use after free-2】

文章目录 fheap libc 2.23 64位检查maincreatedelete 思路覆盖目标函数的指针printf内部调用覆盖的函数前调用 printf时的栈实际去的函数的地方查找当前版本对应的libc_start_main和system计算出system的libc基地址exp fheap libc 2.23 64位 检查 main 多层while&#xff0c;…

Mybatis 缓存

Mybatis 缓存 Mybatis 中有一级缓存和二级缓存&#xff0c;默认情况下一级缓存是开启的&#xff0c;而且是不能关闭的。一级缓存是指 SqlSession 级别的缓存&#xff0c;当在同一个 SqlSession 中进行相同的 SQL 语句查询时&#xff0c;第二次以后的查询不会从数据库查询&…

【Spring】10 BeanFactoryAware 接口

文章目录 1. 简介2. 作用3. 使用3.1 创建并实现接口3.2 配置 Bean 信息3.3 创建启动类3.4 启动 4. 应用场景总结 Spring 框架为开发者提供了丰富的扩展点&#xff0c;其中之一就是 Bean 生命周期中的回调接口。本文将专注于介绍一个重要的接口 BeanFactoryAware&#xff0c;探…

FA2016ASA (MHz范围晶体单元,内置热敏电阻) 汽车

FA2016ASA是爱普生推出的一款内置热敏电阻、频率范围为38.4MHz的晶振&#xff0c;确保数据的准确传输&#xff0c;同时有效避免频谱干扰的出现。可以在-40C to 125C 的温度内稳定工作。在汽车内部空间有限的情况下&#xff0c;FA2016ASA以其小型超薄的外形尺寸2.0 1.6 0.68mm…

多级缓存:亿级流量的缓存方案

文章目录 一.多级缓存的引入二.JVM进程缓存三.Lua语法入门四.多级缓存1.OpenResty2.查询Tomcat3.Redis缓存预热4.查询Redis缓存5.Nginx本地缓存6.缓存同步 一.多级缓存的引入 传统缓存的问题 传统的缓存策略一般是请求到达Tomcat后&#xff0c;先查询Redis&#xff0c;如果未…

buuctf-Misc 题目解答分解91-93

91.[SUCTF2018]followme 下载完就是一个流量包 &#xff0c;用wireshark 打开 直接导出 http对象 这里面 有很多的这样的文件 里面都是参数 直接搜索 关键字 suctf grep -r "SUCTF" 得到flag SUCTF{password_is_not_weak} 92.[MRCTF2020]CyberPunk 用notepad 打开…

论文笔记:Accurate Localization using LTE Signaling Data

1 intro 论文提出LTELoc&#xff0c;仅使用信令数据实现精准定位 信令数据已经包含在已在LTE系统中&#xff0c;因此这种方法几乎不需要数据获取成本仅使用TA&#xff08;时序提前&#xff09;和RSRP【这里单位是瓦】&#xff08;参考信号接收功率&#xff09; TA值对应于信号…

JavaWeb笔记之前端开发CSS

一 、引言 1.1 CSS概念 层叠样式表(英文全称&#xff1a;Cascading Style Sheets)是一种用来表现HTML&#xff08;标准通用标记语言的一个应用&#xff09;或XML&#xff08;标准通用标记语言的一个子集&#xff09;等文件样式的计算机语言。CSS不仅可以静态地修饰网页&…