阶段十-springsecurity总结

news2024/11/16 15:52:55

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.coloradmin.cn/o/1323368.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用GMAT进行卫星轨道仿真

文章目录 设计飞行器预报模型配置轨道图配置预报命令运行和分析 GMAT是一跨开源轨道设计软件&#xff0c;官网挂着NASA的名字&#xff0c;看上去十分给力。 下载之后直接解压&#xff0c;可执行文件在bin目录下&#xff0c;双击GMAT.exe&#xff0c;就可以进入其欢迎界面了。G…

网络编程day4

#include<myhead.h> int task_download(int client_fd,struct sockaddr_in serve_info) {//定义变量存储下载请求包char buf[516] "";//定义变量存储文件名char filename[40] "";printf("请输入文件名&#xff1a;");scanf("%s&quo…

scrapy快加构造并发送请求

scrapy数据建模与请求 学习目标&#xff1a; 应用 在scrapy项目中进行建模应用 构造Request对象&#xff0c;并发送请求应用 利用meta参数在不同的解析函数中传递数据 1. 数据建模 通常在做项目的过程中&#xff0c;在items.py中进行数据建模 1.1 为什么建模 定义item即提前…

PDA智能巡检系统

PDA智能巡检系统是一种基于便携式数字助理&#xff08;PDA&#xff09;设备的智能化巡检管理系统。它利用PDA设备的便携性和智能化特点&#xff0c;结合巡检管理软件和相关技术&#xff0c;实现对设备、设施或场所的全面巡检和管理。在日常巡检、设备巡检、设备点检中发挥着积极…

Maven仓库上传jar和mvn命令汇总

目录 导入远程仓库 命令结构 命令解释 项目pom 输入执行 本地仓库导入 命令格式 命令解释 Maven命令汇总 mvn 参数 mvn常用命令 web项目相关命令 导入远程仓库 命令结构 mvn deploy:deploy-file -Dfilejar包完整名称 -DgroupIdpom文件中引用的groupId名 -Dartifa…

中小型企业网络综合实战案例分享

实验背景 某公司总部在厦门&#xff0c;北京、上海都有分部&#xff0c;网络结构如图所示&#xff1a; 一、网络连接描述&#xff1a; 厦门总部&#xff1a;内部网络使用SW1、SW2、SW3三台交换机&#xff0c;SW1为作为核心交换机&#xff0c;SW2、SW3作为接入层交换机&#x…

【C语言】操作符详解(五)

目录 操作符的属性&#xff1a;优先级&#xff0c;结合性 优先级 结合性 表达式求值 整形提升 算术转换 问题表达式解析 表达式1 表达式2 表达式3 总结 操作符的属性&#xff1a;优先级&#xff0c;结合性 优先级 ⭐优先级&#xff1a;优先级指的是&#xff0c;如果一…

九牧:科技卫浴,长期主义

“没有做错什么&#xff0c;但却输给了时代”&#xff0c;这是人们给当年手机巨头诺基亚的注解。 谁也没有想到&#xff0c;曾在手机行业称雄的诺基亚&#xff0c;最终败给了时代。当年&#xff0c;在2G向3G、4G跨越的时候&#xff0c;苹果、微软的iOS和安卓系统将手机从简单的…

实验三 MapReduce编程

实验目的&#xff1a; 1.掌握MapReduce的基本编程流程&#xff1b; 2.掌握MapReduce序列化的使用&#xff1b; 实验内容&#xff1a; 一、在本地创建名为MapReduceTest的Maven工程&#xff0c;在pom.xml中引入相关依赖包&#xff0c;配置log4j.properties文件&#xff0c;搭…

个人老师可直接使用的在线授课软件

大家好&#xff0c;我是 Java陈序员。 大学四年&#xff0c;疫情就占了三年&#xff01; 以前小时候曾经梦想着不用去学校上课&#xff0c;在家就能上课&#xff0c;这不前几年疫情的时候就成为了现实&#xff01; 随着互联网的兴起&#xff0c;各种线下的活动都可以搬到线上…

sql_lab靶场搭建以及存在的一些问题

sql_lab靶场搭建问题 首先检查小皮版本 把小皮改到5.3.29版本如果没有可以直接点击更多版本进行选择安装 当版本不对时则会暴出这种错误 SETTING UP THE DATABASE SCHEMA AND POPULATING DATA IN TABLES: Fatal error: Uncaught Error: Call to undefined function mysql_co…

SSH的交互原理(wireshark的分析)

SSH的交换原理&#xff08;wireshark篇&#xff09; 首先要想了解ssh的交换原理&#xff0c;必须要先了解他的加密方式&#xff0c;他的加密方式是对称加密&#xff0c;和公钥加密。什么意思呢&#xff1f; 首先我们向服务器发送一个请求&#xff0c;然后服务器会发给我们他的…

5个免费、跨平台的SQLite数据库可视化工具

前言 SQLite是一个轻量级的嵌入式关系型数据库&#xff0c;目前最新的版本是 SQLite3。今天推荐5个实用的SQLite数据库可视化工具(GUI)&#xff0c;帮助大家更好的管理SQLite数据库。 什么是SQLite&#xff1f; SQLite是一个轻量级的嵌入式关系型数据库&#xff0c;它以一个…

3d游戏公司选择云电脑进行云办公有哪些优势

随着游戏行业的不断发展&#xff0c;很多的游戏制作公司也遇到了很多的难题&#xff0c;比如硬件更换成本高、团队协同难以及效率低下等问题&#xff0c;那么如何解决游戏行业面临的这些行业痛点&#xff0c;以及游戏制作公司选择云电脑进行云办公有哪些优势&#xff1f;一起来…

Word的兼容性问题很常见,禁用兼容模式虽步不是最有效的,但可以解决兼容性问题

当你在较新版本的Word应用程序中打开用较旧版本的Word创建的文档时&#xff0c;会出现兼容性问题。错误通常发生在文件名附近&#xff08;兼容模式&#xff09;。兼容性模式问题&#xff08;暂时&#xff09;禁用Word功能&#xff0c;从而限制使用较新版本Word的用户编辑文档。…

查看git的帮助信息

说明 在cmd窗口、或者git Bash shell下执行git --help或者git -h命令&#xff0c;可以查看git的帮助信息。 执行git <command> --help命令可以查看某个命令的帮助信息&#xff0c;其中<command>表示某个具体的命令。 示例1&#xff1a;在git Bash shell下运行git…

JavaOOP篇----第六篇

系列文章目录 文章目录 系列文章目录前言一、String 是最基本的数据类型吗?二、float f=3.4;是否正确?三、short s1 = 1; s1 = s1 + 1;有错吗?short s1 = 1; s1 +=1; 有错吗?四、重载和重写的区别前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住…

嵌入式Linux学习(3)——中断(Interrupt)子系统概念

目录 一. 中断概念与分类 1.1 中断分类 1.2 中断事件的处理流程 1.3 中断号(IRQ number) 1.4 中断源(Interrupt Source) 1.5 中断触发方式 二. 中断子系统架构 2.1 GIC 2.2 中断子系统架构 2.3 GIC与IP 2.3.1 典型GIC IP PLC390 GIC 400 GIC 500 REF 一. 中断概念与…

Git初始

一)git的介绍: 1)假设现在有一个文档&#xff0c;你的老板要求你针对于这份文件进行修改&#xff0c;进行完成的修改的版本是版本1&#xff0c;接下来是文档2&#xff0c;修改完文档2以后&#xff0c;接下来老板还不同意&#xff0c;于是又有了文档三&#xff0c;文档四&#x…

海康rtsp拉流,rtmp推流,nginx部署转flv集成

海康rtsp拉流&#xff0c;rtmp推流&#xff0c;nginx部署转flv集成 项目实际使用并测试经正式使用无问题&#xff0c;有问题欢迎评论留言 核心后台java代码&#xff1a; try {// FFmpeg命令String command "ffmpeg -re -i my_video.mp4 -c copy -f flv rtmp://localho…