Spring Security框架使用详解

---Spring Security是配置在具有登录功能的前后端交互项目中

配置要点:

首先一个项目想要有Spring Security支持,需要先在

1.依赖库里边加上Security和jjwt,fastjson依赖项

  

  

        

            org.springframework.boot

            spring-boot-starter-security

        

        

        

            io.jsonwebtoken

            jjwt

            0.9.1

        

        

        

            com.alibaba

            fastjson

            1.2.75

        

2.写Security配置类,写Jwt过滤器

Security配置类

继承WebSecurityConfigurerAdapter

还有两个重要的Bean要加上,PasswordEncoder以及AuthenticationManager

1约定密码编码格式,2用于后续认证操作的操作器

Security过滤器里边要声明白名单路径,然后制定访问控制策略,比如常用的是将OPTION请求放行

因为OPTION请求是请求中有复杂数据时会出现的一种请求,这种请求并没有实际数据,是由浏览器发起的,只是询问是否可以接收处理复杂请求,算是一个预检,我们可以直接放行,即告诉浏览器OK,

对于其他的请求我们都要求其具有认证.最后在这个配置Security的配置类中我们还要在最后将Jwt的过滤器加进来,因为对于密码等的验证Security框架是自动进行的,我们需要将Jwt的验证优先级提一下,让他在Security自动处理数据之前运行.

Jwt过滤器

Jwt过滤器即是处理那些没有被Security配置通过的请求,当接收到一个请求,本类会先将当前Security上下文中的认证信息清空,然后将请求头里的数据根据约定的消息头Authorization提取出来(未提取到直接放行,未将认证信息写入上下文就等着被拦截),这个对应的就是Jwt,然后对Jwt进行反解析(用到Jwt工具类),这句反解析的代码是可能抛出异常的,Jwt过期以及错误异常,当没有异常抛出时,就认为这个认证信息是有效的,由于往Jwt里边封装数据只能是以Map的形式,这里我们也是用get("")的形式获取到当初存进去的信息,注意存放的时候Map格式约束导致我们拿到的数据都是Object类型,当我们在往Authentication(Security写入上下文约定的格式)放数据的时候还是(Object,Object,Collection)类型,我们可以将诸如id,username这种用户信息封装一下放到第一个参数,第二个参数不管,置为null,至于第三个参数我们需要对数据类型进行转换才能装进去. 转好后写入Security上下文,那么本次请求就是拥有认证的,Security放行

Jwt工具类:

封装将Map数据转为jwt(String),复杂集合需要转为JSON格式在放进去,避免往出拿时格式错乱

封装解析Jwt数据回到Map类型的过程,这里讲一下其中各数据的转换经历

用户名:

AdminDetails[1]是就是个用户名属性,到往jwt转换的时候也是用户名,直到被提取出来往Security上下文里边装的时候才与id封装成为个人主体信息AdminPrincipal

权限:

权限起初都是放在数据库中的字符串,当查询时我们将这一条条权限(String)放到了List集合中,因此我们根据用户名 查询得到的AdminLoginVO中permission是一个List类型,在往AdminDetails中装的时候,由于AdminDetails需要的是一个List<GrantedAuthority>,因此就有了遍历permission,将每一条String数据通过new GrantedAuthority()的方式转换成符合格式约定的类型,这样就将一个AdminDetails数据封装完毕了,送去认证密码(用到PasswordEncoder里边matches).通过后因为要往jwt转换,集合形式的数据放到jwt里边容易出错,因此转换为String(通过JSON当中间人)

JSON.toJSONString(List<>) ,jwt解析出来后又可以

JSON.parseArray(, <集合中数据类型>.class)恢复为List<集合中数据类型>,他会以这个形式写入Security上下文.

[注1]

AdminDetail数据类型是我们因为其原本UserDetails类型没有id属性,UserDetails是User类型的一个实现,因此我们继承了User类再声明一个id属性,然后写了一个具有id属性的构造方法,在方法体中super父类实现 方法,然后将this.id=id;AdminDetails,这样使用AdminDetails创建的数据对象就具有id属性了,后续可get调用.

3.加注解

                在Security配置类上加此注解,开启全局授权访问检查

@EnableGlobalMethodSecurity(prePostEnabled = true)

在Controller方法上加注解,配置访问权限

@PreAuthorize("hasAnyAuthority('/ams/admin/update')")

 

4.登录

用户输入的用户名,密码被封装着传入Controller,然后被解开放到AdminDetails里边根据名字查找对应的对象,没查到就直接返回null,在外边null就直接抛出异常了,不是null就将找到的数据封装起来成为一个AdminDetails对象送到外边进行认证,认证通过就继续往下走,提取(用户名,id,权限) 注意这个信息是放在验证用户登录信息返回的对象的principal中,可以get后直接强转成AdminDetails,注意权限List集合要转为String类型然后往map里边放,最后将map传给Jwt工具类转换成jwt码,以

JsonResult.ok(jwt)

返回,方便前端调用

 

5.前端调用

前端在发送登陆请求,登陆成功后通过response.data.data获取jwt,setItem到localStorage,让其他请求可以直接getItem,然后发请求放上这个请求头

this.axios.create({

            headers: {

              Authorization: jwtItem

            }

          }).post/get…

你可能感兴趣的:(Spring,Security,java框架,java,spring,后端)