当前位置:网站首页>Three annotations, elegant implementation of micro service authentication
Three annotations, elegant implementation of micro service authentication
2022-06-09 18:33:00 【Not just Chen】
Hello everyone , I'm not just Chen ~
This is a 《Spring Cloud Advanced 》 The first 39 An article , The previous article introduced gateway integration Spring Security Realize unified authentication at the gateway level .
If there is something unclear, you can read the previous article : Combat dry goods !Spring Cloud Gateway Integrate OAuth2.0 Realize distributed unified authentication and authorization !
Recently subscribed to 《Spring Cloud Alibaba actual combat 》 Readers of the video column often ask Chen two questions , as follows :
How to do authentication in each micro service ?
feign How to do authentication by calling ?
Today, let's talk about how to solve the above two problems through three annotations .
Digression : Chen will be in B standing 、 Share some video tutorials in official account , After all, the article is difficult to understand .
B Station links :https://b23.tv/wdfX4E6
Below is a video tutorial for this article , Explain in more detail !
“The handsome people all praised ~
”
Realize the idea
In the previous articles, Mr. Chen unified authentication and authentication at the gateway level , The structure is as follows :

There is another way of thinking about authentication in microservices : Give the authentication to the downstream microservices , The gateway layer only does routing forwarding .
This idea is actually very simple to realize , The following code transformation for authentication at the gateway level can be completed : Combat dry goods !Spring Cloud Gateway Integrate OAuth2.0 Realize distributed unified authentication and authorization !
1. Kill the authentication manager
Unified authentication at the gateway is actually a dependent authentication manager ReactiveAuthorizationManager, All requests need to be authenticated by the authentication manager to authenticate the login user's permission .
This authentication manager is also introduced in the article on gateway authentication , In Chen's 《Spring Cloud Alibaba actual combat 》 It is also easy to configure interception in , as follows :

In addition to the configured white list , All other requests must be intercepted and authenticated by the authentication manager of the gateway , Only after authentication can the route be released and forwarded to the downstream service .
Is it clear to see the train of thought here , You want to give authentication to downstream services , It only needs to be released directly at the gateway level , Do not use the authentication manager , The code is as follows :
http
....
// White list direct release
.pathMatchers(ArrayUtil.toArray(whiteUrls.getUrls(), String.class)).permitAll()
// Any other request for direct release
.anyExchange().permitAll()
.....2. Define three annotations
After the first ① Step , Authentication has been delegated to downstream services , So how do downstream services intercept and authenticate ?
Actually Spring Security Provides 3 Annotations are used to control permissions , as follows :
@Secured@PreAuthorize@PostAuthorize
These three notes will not be introduced in detail , If you are interested, you can consult the official documents .
Chen doesn't plan to use the three built-in annotations to realize , Instead, three annotations are customized , as follows :
See the name and know the meaning , Only when the user logs in can it be released , The code is as follows :
/**
* @author official account : Code ape technology column
* @url: www.java-family.cn
* @description Notes for login authentication , Marked on controller On the way , Must be a login to access the interface
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface RequiresLogin {
}See the name and know the meaning , Only those with the specified authority can be released , The code is as follows :
/**
* @author official account : Code ape technology column
* @url: www.java-family.cn
* @description Marked on controller On the way , Ensure that you have the specified permissions to access the interface
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface RequiresPermissions {
/**
* Permission code to be verified
*/
String[] value() default {};
/**
* Verification mode :AND | OR, Default AND
*/
Logical logical() default Logical.AND;
}See the name and know the meaning , Only the specified role can be released , The code is as follows :
/**
* @author official account : Code ape technology column
* @url: www.java-family.cn
* @description Marked on controller On the way , Ensure that you have the specified role to access the interface
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface RequiresRoles {
/**
* Role ID to be verified , Default override and Administrator
*/
String[] value() default {OAuthConstant.ROLE_ROOT_CODE,OAuthConstant.ROLE_ADMIN_CODE};
/**
* Verification logic :AND | OR, Default AND
*/
Logical logical() default Logical.AND;
}The meaning of the above three notes must be well understood , No more explanation here ....
3. Annotation facet definition
The annotation has , So how to intercept ? Here, Chen defines an aspect to intercept , The key codes are as follows :
/**
* @author official account : Code ape technology column
* @url: www.java-family.cn
* @description @RequiresLogin,@RequiresPermissions,@RequiresRoles Section of annotation
*/
@Aspect
@Component
public class PreAuthorizeAspect {
/**
* structure
*/
public PreAuthorizeAspect() {
}
/**
* Definition AOP Signature ( Cut into all methods that use authentication annotations )
*/
public static final String POINTCUT_SIGN = " @annotation(com.mugu.blog.common.annotation.RequiresLogin) || "
+ "@annotation(com.mugu.blog.common.annotation.RequiresPermissions) || "
+ "@annotation(com.mugu.blog.common.annotation.RequiresRoles)";
/**
* Statement AOP Signature
*/
@Pointcut(POINTCUT_SIGN)
public void pointcut() {
}
/**
* Circle cut
*
* @param joinPoint Tangent object
* @return The return value of the underlying method after execution
* @throws Throwable Exceptions thrown by the underlying method
*/
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// Annotation authentication
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
checkMethodAnnotation(signature.getMethod());
try {
// Execute the original logic
Object obj = joinPoint.proceed();
return obj;
} catch (Throwable e) {
throw e;
}
}
/**
* To a Method Object for annotation checking
*/
public void checkMethodAnnotation(Method method) {
// check @RequiresLogin annotation
RequiresLogin requiresLogin = method.getAnnotation(RequiresLogin.class);
if (requiresLogin != null) {
doCheckLogin();
}
// check @RequiresRoles annotation
RequiresRoles requiresRoles = method.getAnnotation(RequiresRoles.class);
if (requiresRoles != null) {
doCheckRole(requiresRoles);
}
// check @RequiresPermissions annotation
RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class);
if (requiresPermissions != null) {
doCheckPermissions(requiresPermissions);
}
}
/**
* Verify whether there is login
*/
private void doCheckLogin() {
LoginVal loginVal = SecurityContextHolder.get();
if (Objects.isNull(loginVal))
throw new ServiceException(ResultCode.INVALID_TOKEN.getCode(), ResultCode.INVALID_TOKEN.getMsg());
}
/**
* Verify whether there is a corresponding role
*/
private void doCheckRole(RequiresRoles requiresRoles){
String[] roles = requiresRoles.value();
LoginVal loginVal = OauthUtils.getCurrentUser();
// The corresponding role of the login user
String[] authorities = loginVal.getAuthorities();
boolean match=false;
//and Logic
if (requiresRoles.logical()==Logical.AND){
match = Arrays.stream(authorities).filter(StrUtil::isNotBlank).allMatch(item -> CollectionUtil.contains(Arrays.asList(roles), item));
}else{ //OR Logic
match = Arrays.stream(authorities).filter(StrUtil::isNotBlank).anyMatch(item -> CollectionUtil.contains(Arrays.asList(roles), item));
}
if (!match)
throw new ServiceException(ResultCode.NO_PERMISSION.getCode(), ResultCode.NO_PERMISSION.getMsg());
}
/**
* TODO Realize it by yourself , Because the front-end menu permissions are not integrated , Implement by yourself according to business requirements
*/
private void doCheckPermissions(RequiresPermissions requiresPermissions){
}
}In fact, the logic is very simple , It's analytic Token The permissions 、 The role is then compared with the one specified in the annotation .
“”
@RequiresPermissionsThe logic of this annotation has not been realized by Chen , Imitate and complete according to the business , It's a thinking problem ....
4. Annotations use
such as 《Spring Cloud Alibaba actual combat 》 There is an interface to add articles in the project , Only the roles of supervisor and administrator can be added , Then you can use @RequiresRoles Annotate , as follows :
@RequiresRoles
@AvoidRepeatableCommit
@ApiOperation(" Add the article ")
@PostMapping("/add")
public ResultMsg<Void> add(@RequestBody @Valid ArticleAddReq req){
.......
}The effect will not be demonstrated here , The actual effect : Non hypervisor and administrator role users log in and access , Will be directly blocked , Return no permission .
Be careful : This only solves the problem of downstream service authentication , that feign Whether the call also applies ?
Of course , Here we use the section method ,feign In fact, what we use inside is http Way to call , The same applies to interfaces .
such as 《Spring Cloud Alibaba actual combat 》 The interface to get the list of articles in the project , It will pass feign Call the interface in the comment service to get the total number of article comments , Once you add @RequiresRoles, Then the call will fail , The code is as follows :
@RequiresRoles
@ApiOperation(value = " Total number of articles obtained in batch ")
@PostMapping(value = "/list/total")
public ResultMsg<List<TotalVo>> listTotal(@RequestBody @Valid List<CommentListReq> param){
....
}summary
This article mainly introduces how to delegate authentication to microservices , It is also to solve the readers' doubts , In actual production, unless the business needs , Chen still suggests that authentication be unified in the gateway .
And finally ( Don't whore for nothing , Please pay attention to )
Chen's every article is carefully output , Has written 3 A column , Put it in order PDF, Here's how to get it :
《Spring Cloud Advanced 》PDF: Official account :【 Code ape technology column 】 Reply key words Spring Cloud Advanced obtain !
《Spring Boot Advanced 》PDF: Official account :【 Code ape technology column 】 Reply key words Spring Boot Advanced obtain !
《Mybatis Advanced 》PDF: Official account :【 Code ape technology column 】 Reply key words Mybatis Advanced obtain !
If this article helps you , Or if there's some inspiration , Give me a favor 、 Looking at 、 forward 、 Collection , Your support is the biggest driving force for me to persevere !
Handsome people are praising 、 Share 、 Looking at San Lian 
边栏推荐
- [MySQL string data type optimization] the difference between char and varchar
- [data processing] pandas reads SQL data
- [notes of advanced mathematics] Green formula, Gauss formula, Stokes formula, field theory
- redis源码学习-03_动态字符串SDS
- 直播预告 | 在阿里云 ESSD 云盘上部署 PolarDB for PostgreSQL 集群
- Redis source code learning-05_ Dictionary, hash table
- 贤弟单腾,因崔思婷,机器人类打字~~~~~~
- Customer information management, business scenario 1
- 身为程序猿——谷歌浏览器的这些骚操作你真的会吗
- 10个常见触发IO瓶颈的高频业务场景
猜你喜欢

如何搭建组态王与欧姆龙PLC之间无线Host-Link通信?

外汇交易MT4是什么软件?MT4与MT5有何区别?下载MT4要注意什么?

Do your filial duty to make an old people's fall prevention alarm system for your family

【高阶知识】用户态协议栈之Epoll实现原理

CAM350检查gerber与钻孔文件

循环结构程序设计2

AD PCB画图注意点

CORTEX-A9三星iTOP-4412开发开发板入门嵌入式

MySQL删除方法delete、truncate、drop的区别是什么
![[high level knowledge] epoll implementation principle of user mode protocol stack](/img/47/1ab66811bdd90ec1365a4a1e18d940.png)
[high level knowledge] epoll implementation principle of user mode protocol stack
随机推荐
陈某的技术交流群招人~
11年程序员给本科、研究生应届生以及准备从事后台开发同学的建议,学习进阶之路
Pcap 文件
SQL topic sorting
Introduction to Multivariate Statistics
深度学习与CV教程(13) | 目标检测 (SSD,YOLO系列)
Redis基础与高级
美化Aria主题媲美收费主题Mirages
redis源码学习-01_Clion中调试redis源码
循环结构程序设计2
[work with notes] multiple coexistence of ADB, sound card, network card and serial port of Tina system
如何通过A/B测试提升Push推送消息点击率?
CAM350检查gerber与钻孔文件
Golang基础(5)
SPI通信原理+Verilog实现及仿真(完整代码)
Golang Foundation (5)
Illustration | cache system consistency for high performance server design
[notes of advanced mathematics] Green formula, Gauss formula, Stokes formula, field theory
What are the reasons for frequent channel drops in easycvr cascading easycvr?
Redis source code learning-05_ Dictionary, hash table