经过我翻来覆去的思想斗争了一个月,最后做出了一个明智的决定

阅读: 评论:0

经过我翻来覆去的思想斗争了一个月,最后做出了一个明智的决定

经过我翻来覆去的思想斗争了一个月,最后做出了一个明智的决定

最近写了几个Spring Boot组件,项目用什么功能就引入对应的依赖,配置配置就能使用,香的很!那么Spring Security能不能也弄成模块化,简单配置一下就可以用上呢?JWT得有,RBAC动态权限更得有!花了小半天就写了个组件,用了一个月感觉还不错。是我一个人爽?还是放出来让大家一起爽?经过我翻来覆去的思想斗争了一个月,最后做出了一个明智的决定,放出来让想直接上手的同学直接使用。源码地址就在下面:

用法

集成

这就是一个Spring Boot Starter,你自己打包、安装。然后引用到项目:

        <dependency><groupId>cn.felord.security</groupId><artifactId>security-enhance-spring-boot-starter</artifactId><version>${version}</version></dependency>

另外你需要集成Spring Cache,比如Redis Cache:

    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apachemons</groupId><artifactId>commons-pool2</artifactId></dependency>

JWT会被缓存到以usrTkn为key的缓存中,如果你想定制的话,自行实现一个JwtTokenStorage并注入Spring IoC就可以覆盖下面的配置了:

    @Bean@ConditionalOnMissingBeanpublic JwtTokenStorage jwtTokenStorage() {return new SpringCacheJwtTokenStorage();}

你应该去了解如何自定义Spring Cache的过期时间。

数据库表设计

然后是数据库表设计,这里简单点弄个RBAC的设计,仅供参考,你可以根据你们的业务改良。

用户表

user_idusernamepassword
1312434534felord{noop}12345

角色表

role_idrole_namerole_code
12343667867管理员ADMIN

用户角色关联表

user_role_iduser_idrole_id
12354657777131243453412343667867

一个用户可以持有多个角色,一个角色在一个用户持有的角色集合中是唯一的。

资源表

resources_idresources_nameresource_patternmethod
12543667867根据ID获取商品/goods/{goodsId}GET

资源其实就是我们写的Spring MVC接口,这里支持ANT风格,但是尽量具体,为了灵活性考虑不推荐使用通配符。

角色资源表

role_res_idrole_idresources_id
45454664451234366786712543667867

一个资源可以关联多个角色,一个角色不能重复持有一个资源。

实现UserDetailsService

实现用户加载服务接口UserDetailsService是Spring Security开发的必要步骤,跟我以前的教程差不多。

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {UserInfo userInfo = this.lambdaQuery().eq(UserInfo::getUsername, username).one();if (Objects.isNull(userInfo)) {throw new UsernameNotFoundException("用户:" + username + " 不存在");}String userId = UserId();boolean enabled = Enabled();Set<String> roles = RolesByUserId(userId);roles.add(“"ANONYMOUS"”);Set<GrantedAuthority> roleSet = roles.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).Set());return new SecureUser(userId,Secret(),enabled,enabled,enabled,enabled,roleSet);
}

这里要说一下里面为啥要内置一个ANONYMOUS角色给用户。如果希望特定的资源对用户全量开放,可配置对应的权限角色编码为ANONYMOUS。当某个资源的角色编码为ANONYMOUS时,即使不携带Token也可以访问。一般情况下匿名能访问的资源不匿名一定能访问,当然你如果不希望这样的规则存在干掉就是了。

查询用户的权限集

实现用户角色权限方法Function<Set<String>, Set<AntPathRequestMatcher>>并注入Spring IoC,根据用户持有的角色集合查询用户可访问的资源列表。这个基于前几天的动态权限文章实现的具体可以去了解。也可以根据当前资源的AntPathRequestMatcher来查询用户是否持有对应的角色,这个你自行改造。

配置

最后就是配置了,跟我以前教程中的配置几乎一样,application.yaml的配置为:

# jwt 配置
jwt:cert-info:# keytool 密钥的 alias alias: felord# 密匙密码key-password: i6x123akg15v13# 路径 这里是在resources 包下cert-location: jwt.jksclaims:# jwt iss 字段值issuer: # sub 字段subject: all# 过期秒数expires-at: 604800

最后别忘记弄个配置类并标记@EnableSpringSecurity以启用配置:

@EnableSpringSecurity
@Configuration(proxyBeanMethods = false)
public class SecurityConfiguration {/*** Function function.** @param resourcesService the resources service* @return the function*/@BeanFunction<Set<String>, Set<AntPathRequestMatcher>> function(IResourcesService resourcesService){return resourcesService::matchers;}@BeanUserDetailsService userDetailsService(IUserInfoService userInfoService){return userInfoService::loadUserByUsername; }}

记得使用@EnableCaching开启并配置缓存。

使用

登录接口

 POST /login?username=felord&password=12345 HTTP/1.1Host: localhost:8080

然后会返回一对JWT,返回包含两个token主体

  • accessToken 用来日常进行请求鉴权,有过期时间。

  • refreshTokenaccessToken过期失效时,用来刷新accessToken

结构为:

{"accessToken": {"tokenValue": "","issuedAt": {"epochSecond": 1616827822,"nano": 393000000},"expiresAt": {"epochSecond": 1616831422,"nano": 393000000},"tokenType": {"value": "Bearer"},"scopes": ["ROLE_ADMIN","ROLE_ANONYMOUS"]},"refreshToken": {"tokenValue": "","issuedAt": {"epochSecond": 1616827822,"nano": 393000000},"expiresAt": null},"additionalParameters": {}
}

调用根据ID获取商品接口时加入Token:

GET /goods/234355451 HTTP/1.1
Host: localhost:8080
Authorization: JzdWIiOiJ1NzgsImlhdCI6MTYxNjkxODk3OCwianRpIjoiNThlOTQktNGVlYzc3MDU0ZDk3In0.ZQcN0FX7_taohqPiC1KnoF7

是不是简单多了?觉得好就给个关注、点赞、转发、再看

我踩过的Spring Boot统一返回体中的坑

2021-04-25

Spring Security 实战干货:Spring Security中的单元测试

2021-04-23

本文发布于:2024-02-01 16:08:05,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170677488637828.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:出了   一个月   翻来覆去   明智   思想
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23