1.Spring Security简介

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

1.1.需求

实现权限校验,指定用户可以访问指定页面

1.2代码解读分析

1).继承WebSecurityConfigurerAdapter

2).重写 configure 方法

 protected void configure(HttpSecurity httpSecurity)

注:此方法用来添加校验规则

/**
* anyRequest | 匹配所有请求路径
* access | SpringEl表达式结果为true时可以访问
* anonymous | 匿名可以访问
* denyAll | 用户不能访问
* fullyAuthenticated | 用户完全认证可以访问(非remember-me下自动登录)
* hasAnyAuthority | 如果有参数,参数表示权限,则其中任何一个权限可以访问
* hasAnyRole | 如果有参数,参数表示角色,则其中任何一个角色可以访问
* hasAuthority | 如果有参数,参数表示权限,则其权限可以访问
* hasIpAddress | 如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
* hasRole | 如果有参数,参数表示角色,则其角色可以访问
* permitAll | 用户可以任意访问
* rememberMe | 允许通过remember-me登录的用户访问
* authenticated | 用户登录后可访问
*/
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// CSRF禁用,因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/captchaImage").anonymous()
.antMatchers(
HttpMethod.GET,
"/*.ttf",
"/*.woff",
"/*.gif",
"/*.eot",
"/*.json",
"/*.woff2",
"/*.png",
"/*.ico",
"/*.svg",
"/*.jpg",
"/*.html",
"/**/*.ttf",
"/**/*.woff",
"/**/*.gif",
"/**/*.eot",
"/**/*.json",
"/**/*.woff2",
"/**/*.png",
"/**/*.ico",
"/**/*.svg",
"/**/*.jpg",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).permitAll().
antMatchers(
//mybatis复习相关的接口全部放行,同学们可以通过postMan进行测试而不需要进行权限认证
"/review/**",
"/review"
).permitAll()
.antMatchers("/common/downloadByMinio**").permitAll()
.antMatchers("/profile/**").anonymous()
.antMatchers("/common/download**").anonymous()
.antMatchers("/common/download/resource**").anonymous()
.antMatchers("/webjars/**").anonymous()
.antMatchers("/*/api-docs").anonymous()
.antMatchers("/druid/**").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable();
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
}

上面有个jwt的过滤器

里面继承了一个类

如果请求中有token则放行

2).添加权限

那么 它是怎么添加权限的那?我们点进参数里看看...

可以看到里面是个接口,返回对象是个

咦。。。这个是不是放用户名和密码 和权限的那,那么看看它的实现类是怎么写的吧

   @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUser user = userService.selectUserByUserName(username);
if (StringUtils.isNull(user)) {
log.info("登录用户:{} 不存在.", username);
throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
}
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
log.info("登录用户:{} 已被删除.", username);
throw new BaseException("对不起,您的账号:" + username + " 已被删除");
}
else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
log.info("登录用户:{} 已被停用.", username);
throw new BaseException("对不起,您的账号:" + username + " 已停用");
} return createLoginUser(user);
}

可以看到首先根据用户名去查对象,并做了一系列判断,最后通过之后调用了这个方法

这个完成对象的初始化,那么这个调用的service又是干什么的那?

这个是把该用户所对应的全部权限,从数据库中查询出来存入集合中,完成对象初始化的

我们再回到之前的配置类

至此,该用户的所拥有的全部权限就获取到了,完成了每个用户所看到的界面不一样的情况,但是这个还要结合一个注解来使用

@PreAuthorize("@ss.hasPermi('clues:course:list')")

这个注解为 spring security 的原生注解 里面返回布尔类型数据,为true就走这个方法

点进去有这么个方法,是不是很熟悉,集合参数里放的就是刚才该用户的权限列表集合,如果包含传进来的字符串,则返回true让其访问,至此功能就实现了

2.SpringBoot中JWT是如何使用的

 JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。

一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。中间用点(.)分隔成三个部分。注意JWT 内部是没有换行的。

2.1.优点

基于token的验证方式它有什么优点吗?

支持跨域访问,Cookie是不允许跨域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输.

无状态:Token机制在服务端不需要存储session信息,因为Token自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息.

解耦 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可.

适用性更广:只要是支持http协议的客户端,就可以使用token认证。

服务端只需要验证token的安全,不必再去获取登录用户信息,因为用户的登录信息已经在token信息中。

基于标准化:你的API可以采用标准化的 JSON Web Token (JWT).

2.1.1.组成

一个JWT实际上就是一个字符串,它由三部分组成,头部、载荷与签名。中间用点(.)分隔成三个部分。注意JWT 内部是没有换行的。

2.2.使用

1).当前端传过来登录请求数据时,把对象生成Token存起来

    public String createToken(LoginUser loginUser) {
String token = IdUtils.fastUUID();
loginUser.setToken(token);
setUserAgent(loginUser);
refreshToken(loginUser); Map<String, Object> claims = new HashMap<>();
claims.put(Constants.LOGIN_USER_KEY, token);
//存放非敏感信息
claims.put("username",loginUser.getUsername());
claims.put("nickName",loginUser.getUser().getNickName());
claims.put("createTime",loginUser.getUser().getCreateTime());
return createToken(claims);
}

这里用了两个方法

第一个:

    /**
* 设置用户代理信息
*
* @param loginUser 登录信息
*/
public void setUserAgent(LoginUser loginUser)
{
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
loginUser.setIpaddr(ip);
loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
loginUser.setBrowser(userAgent.getBrowser().getName());
loginUser.setOs(userAgent.getOperatingSystem().getName());
}

设置代理信息

第二个:

 /**
* 刷新令牌有效期
*
* @param loginUser 登录信息
*/
public void refreshToken(LoginUser loginUser)
{
loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
// 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken());
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
}

刷新令牌有效期,并将对象存入Redis中

最后调用了这个方法,返回生成的令牌

  /**
* 从数据声明生成令牌
*
* @param claims 数据声明
* @return 令牌
*/
private String createToken(Map<String, Object> claims)
{
String token = Jwts.builder()
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret).compact();
return token;
}

secret为签名,保证数据安全性

2).接下来我们看看如何取出来

可以看到我们传进去的是一个HttpServletRequest请求,因为我们把Token放请求头里了,那么我们点进去看看,是怎么取的

这个方法总共调用了这三个方法,最终取出来了user对象,接下来一步一步看吧

第一个方法获取Token字符串

第二个方法根据Token字符串获取集合

第三个方法根据Token存入的唯一的UUID获得存入缓存中的key

最终取到user对象,至此Token存取完成。

以上为个人梳理,有不对的地方还请指正

SpringSecurity+Token实现权限校验的更多相关文章

  1. SpringCloud(8)---zuul权限校验、接口限流

    zuul权限校验.接口限流 一.权限校验搭建 正常项目开发时,权限校验可以考虑JWT和springSecurity结合进行权限校验,这个后期会总结,这里做个基于ZuulFilter过滤器进行一个简单的 ...

  2. 基于SpringSecurity的@PreAuthorize实现自定义权限校验方法

    一.前言 在我们一般的web系统中必不可少的就是权限的配置,也有经典的RBAC权限模型,是基于角色的权限控制.这是目前最常被开发者使用也是相对易用.通用权限模型.当然SpringSecurity已经实 ...

  3. 关于Token和Cookie做权限校验的区别及Token自动续期方案

    title: 关于Token和Cookie做权限校验的区别及Token自动续期方案 categories: 后端 tags: - .NET Token和Cookie的区别 首先,要知道一些基本概念:h ...

  4. ruoyi接口权限校验

    此文章属于ruoyi项目实战系列 ruoyi系统在前端主要通过权限字符包含与否来动态显示目录和按钮.为了防止通过http请求绕过权限限制,后端接口也需要进行相关权限设计. @PreAuthorize使 ...

  5. 微服务架构 - 搭建docker本地镜像仓库并提供权限校验及UI界面

    搭建docker本地镜像仓库并提供权限校验及UI界面 docker本地镜像仓库的作用跟maven私服差不多,特别是公司级或者是小组级开发好的docker仓库可以上传到本地镜像仓库中,需要用时,直接从本 ...

  6. ASP.NET Core 实战:基于 Jwt Token 的权限控制全揭露

    一.前言 在涉及到后端项目的开发中,如何实现对于用户权限的管控是需要我们首先考虑的,在实际开发过程中,我们可能会运用一些已经成熟的解决方案帮助我们实现这一功能,而在 Grapefruit.VuCore ...

  7. fastDFS shiro权限校验 redis FreeMark页面静态化

    FastDFS是一个轻量级分布式文件系统,   使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传.下载等服务   FastDFS服务端有两个角色:跟踪器(tracker)和存储节点( ...

  8. Vuejs实战项目四:权限校验

    路由跳转参考文档:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html 在/src下创建permission.js进行权限 ...

  9. drf 权限校验设置与源码分析

    权限校验 权限校验和认证校验必须同时使用,并且权限校验是排在认证校验之后的,这在源码中可以查找到其执行顺序. 权限校验也很重要,认证校验可以确保一个用户登录之后才能对接口做操作,而权限校验可以依据这个 ...

  10. 【SpringBoot技术专题】「权限校验专区」Shiro整合JWT授权和认证实现

    本章介绍一下常用的认证框架Shiro结合springboot以及集合jwt快速带您开发完成一个认证框架机制. Maven配置依赖 <dependency> <groupId>o ...

随机推荐

  1. turtle绘制风轮

    题目要求: 使用turtle库,绘制一个风轮效果,其中,每个风轮内角为45度,风轮边长150像素. 我的代码: import turtle turtle.setup(500,500,100,200) ...

  2. idea修改背景颜色|护眼色|项目栏背景修改

    https://blog.csdn.net/heytyrell/article/details/89743068

  3. 在VS中C#工程操作Mysql数据库

    1.实现mysql数据库与VS的连接,需要安装两个插件,作者装的是mysql-connector-net-6.9.9.msi和 mysql-for-visualstudio-1.2.6.msi. 2. ...

  4. react+ant-design-proTable 设置搜索条件中的默认值

    需求: 这个规则组ID的 下拉列表是通过向后端请求获取的,如何设置自定义渲染列表,并且默认有值 let groupLists = [] as any, //规则组列表 defaultValue = ' ...

  5. SpringBoot整合RocketMQ案例实战

    一.概念 rocketMQ是一款典型的分布式架构下的中间件产品,使用异步通信方式和发布订阅的消息传输模型,具备异步通信的优势,系统拓扑简单,上下游耦合较弱,主要应用于异步解耦,流量削峰填谷等场景 二. ...

  6. Shell脚本之while read line的用法

    Shell脚本之while read line的用法 while read line do - done < file read通过输入重定向,把file的第一行所有的内容赋值给变量line,循 ...

  7. 统一观测丨使用 Prometheus 监控 E-MapReduce,我们该关注哪些指标?

    作者:闻洪 开源大数据平台E-MapReduce(简称"EMR")是云原生开源大数据平台,向客户提供简单易集成的Hadoop.Hive.Spark.Flink.Presto.Cli ...

  8. Android笔记--修改Device File Explorer的文件打开方式

    在首次打开该文件时,不小心选错了打开方式,导致以后每次打开也是同样的打开方式,也不会弹出第一次那样的打开方式的选择弹窗 在这里提供修改文件的默认打开方式的方法: 首先通过File->settin ...

  9. 震惊,一行MD5居然让小伙伴都回不了家!!!

    作者:京东零售 付伟 1. 前言 大家好,当你点开这篇文章的时候也许心想是哪个 XX 小编混到这里,先不要着急扔臭鸡蛋,本文是一篇标准(正经)的问题复盘文章.好了,一行MD5居然让小伙伴下不了班,到底 ...

  10. 基于 Gitlab + Harbor + K8s + Kuboard 的 CI 实践

    CI/CD 概念 CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法.CI/CD 的核心概念是持续集成.持续交付和持续部署.作为一种面向开发和运维团队的解决方案,CI/CD 主要 ...