Spring(Boot) Security 拦截登录封装问题咨询请教

2020-02-01 12:02:15 +08:00
 yanyueio

大佬们,请问您有做过类似 @login 这类拦截登录的封装么?

例如某个 RequestMapping(URL) 方法上,只要加了这个注解,它就自动处理拦截,包括 next 跳转等工作?

不晓得我的表述是否到位,大概的意思应该说了,总而言之:

个人觉得 Spring Security 这类重写 WebSecurityConfigurerAdapter 的方式实在太老土且麻烦。

大佬们请不吝指点一下(秀出您超 man 的肌肉吧)。

因为有点赶时间,如果有现成的最好。。。做伸手党实在不好意思啦

3562 次点击
所在节点    程序员
16 条回复
tairan2006
2020-02-01 13:22:43 +08:00
自己写注解能有多麻烦…
tangtj
2020-02-01 13:22:59 +08:00
启动后从容器获取`RequestMappingHandlerMapping`,获取所有`HandlerMethod`拿到自己标记了注解的方法.
实现`AccessDecisionVoter`接口,在逻辑内对访问的 url 做判断实现.
把实现配置到`accessDecisionManager()`
k9990009
2020-02-01 14:01:28 +08:00
自定义注解鉴权,就是启动的时候查找所有 controller,然后找到所有标记了你自定义的注解的 url 及对应所需的角色权限,加个拦截器检查就完了。简单点,你注解也不用写了,就请求 url 加前缀,拦截器根据前缀处理。
yanyueio
2020-02-01 14:33:12 +08:00
@k9990009 我理解您的思路大致是:

```java
//在 preHandle(HttpServletRequest request) 里面
//拦截器处理用户权限
String uri = request.getRequestURI();
if (uri.startsWith("/admin") && !uri.startsWith("/admin/login")) {
//这里先不处理登录后的跳转问题
response.sendRedirect(request.getContextPath() + "/admin/login");
return false;
}
```

然而,这样做的话,SpringSecurity 里面还配置么?即 authroizeReqests() 那套逻辑。

```java
config(HttpSecurity http) {
http.authorizeRequests().antMatchers("/admin/**").accsess("hasRole('ADMIN')")
.and() .... //blabla
}
```

我这边权鉴还是在 SpringSecurity 逻辑里面,具体说就是 `AuthenticationManagerBuilder`,用的 jdbc auth 那套处理的 user, role,之后配置 config(HttpSecurity http) 这里的时候就发现这样配置 Mapping URL 的逻辑不利于后续扩展,比如后面又增加了其他正则类型的 URL,**写完 Controller 就要过来改这边**。

而自己写拦截器只判断 URL 这一边,那么 SpringSecurity 那套不配置啦?如果配置,那么是不是比原来功夫更多了。

还是感谢您分享自己的经验。
kanezeng
2020-02-01 16:35:06 +08:00
@yanyueio 我大概记得以前类似这么用拦截器干过,在 preHandle 里去取对应方法的 RequiredPermission 注解,如果有有就判断里面提供的权限。没有再配置 SpringSercurity 了。不过那些都是些小项目,基本上权限管理,登陆验证,token 生成存储与验证之类的都是土法炼钢一整套
jorneyr
2020-02-01 17:00:07 +08:00
1. 实现自定义注解并在 Spring 中生效,可以参考 https://qtdebug.com/spring-core-aspectj-custom-annotation
2. 在注解中获取当前用户的信息,该判断登录的判断登录,该判断权限的判断权限即可,如果不满足条件,未登录的跳转到登录页面,登录了的权限不够进行提示
qinxi
2020-02-01 17:54:37 +08:00
关键流程:

1. 开启注解拦截
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)

2. 在 AuthenticationProvider 中给 AuthenticationToken 增加 GrantedAuthority

3.方法或类上增加 @PreAuthorize("hasAuthority(T(com.xxx.enums.Role).ADMIN.name())") 或者通过 HttpSecurity#authorizeRequests 配置
zhaoyou
2020-02-01 18:18:22 +08:00
自己在拦截器里面控制不香吗?多个拦截器,定义顺序,不同的路径不同的权限。Spring security 对我来说有点重!
zhang5388137
2020-02-01 18:24:38 +08:00
这个不就是 自定义的拦截器 里面自定义的注解吗
hantsy
2020-02-01 18:37:45 +08:00
过去多年的经验,Annoations 方式不是很好用。Java EE 规范中是这样为主。

对于 Http 访问,URI 拦截才是最简单的,集中配置更简单。

Spring Security 支持三种 Annotations。
1. Secured
2. PreAuthorize, PostAuthorize
3. Java EE 兼容 Annotations

从系统设计的角度,定义一个自己的 Adapter 集中处理安全配置。

1. 将 Security 配置从业务代码分离出来,也是一种解耦吧。
2. 可以使用编程方式配置,也就是说安全属性可以写到数据库或者其它地方,并且可以动态配置(中国人不是喜欢界面配置权限,这种方式很容易实现)。
3. 更容易写测试,测试逻辑时完全可以将安全配置 Disable 掉(如果你写测试的话)。
yanyueio
2020-02-01 18:59:57 +08:00
@qinxi 这个大致和我最初想的差不多了。
@hantsy 您这么一说,貌似也是这么个设计思想,当初没想到是业务代码解耦。

感谢众位大佬点播,个人感觉在 @qinxi 的基础上再封装一次是可行的。

再次感谢。
hantsy
2020-02-01 19:26:19 +08:00
@qinxi
1. 第一步中,如果是使用最新 Spring Boot,不要添加 @EnableWebSecurity,Spring Boot AutoConfiguration 会对添加默认 Spring Security 配置。
1. 添加 @EnableWebSecurity 会破坏默认配置。
2. 而一个普通 @Configuration WebSecurityConfigurerAdapter bean 会在默认配置基础上添加自己的配置。

类似在 Spring Boot 中,@EnableWebMVC, @Enable***repsitories 都不要使用。配置自己项目时,参阅 SpringBoot 文档,大部分默认配置可以通过修改 applicaiton.properties|yaml 简单的完成。
2. 最简单的实现,只需要配置一个 UserDetailsService Bean。除非你想改变 Anthentication 内部机制,才需要自己的 AnthenticationProvider。
qinxi
2020-02-01 23:01:38 +08:00
@hantsy #12 因为我使用到自定义以及多种认证方式结合的登录,所以我的 filter,provider,token,handle 都是自己实现的.

就算是使用默认实现,也是同样的流程.区别在于谁实现的问题
abcbuzhiming
2020-02-02 11:48:25 +08:00
Spring security 实现的非常学术化,很多地方很死板,尤其是对登录处理器的配置,一点都不如 shiro 灵活,我不建议用这个库,甚至 spring 自己的社区用的都是 shiro
hantsy
2020-02-02 12:32:25 +08:00
@abcbuzhiming 当你要支持各种协议的时候,你就发现 Shiro 多少简陋。
hantsy
2020-02-02 12:44:30 +08:00
@qinxi Spring Security 5 内部支持 Http Basic, Spring Session (一种 Token 机制),X509 安全证书, user/password login form, 和 OAuth2/OIDC 协议,这个衍生的子协议太多了,内部支持一些实现,包括 twitter,facebook, google, okta, github 等,其它的 Oauth2/Oidc 兼容协议一样可以配置(复杂一点)。

对于多种安全配置,我倾向于使用成熟方案,比如 Keycloak,还有 Cloud 服务,比如 Okta,Auth0. 可以轻松配置集成多种登录一起,比如 2fa, otp, 普通的 user/password , social ( OAuth2 ) 等,这些服务都可以很好与 Spring Security 5 集成。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/641352

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX