5个构建Spring Boot API的实用技巧

建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!

每个API开发人员都在寻找一种更安全地管理其应用程序,而又不牺牲速度或易于实现新功能的方法。 为此,我们最近将核心Stormstorm产品(我们的REST API)更新为Spring Boot。 在此过程中,我们利用了许多关键效率,这对于任何使用Spring Boot开发API的人来说都是有价值的。

许多团队发现很难管理对其API的身份验证和访问控制,因此我们希望分享迁移中的一些体系结构原理和技巧,以简化管理Spring Boot API的过程。

注意:下面我们使用命令行工具httpie(https://github.com/jkbrzt/httpie)来练习示例。

1.使用@RestController注释

使用@RestController (而不是简单地@Controller )可确保您将返回Java对象,而不是对HTML模板的引用。 像这样:

@RestController
public class HelloController {@RequestMapping("/")public String home() {return "hello";}
}

执行: http -v localhost:8080

HTTP/1.1 200 OK
Content-Length: 5
Content-Type: text/plain;charset=UTF-8
Date: Tue, 14 Jun 2016 23:55:16 GMT
Server: Apache-Coyote/1.1hello

2.利用自动POJO到JSON转换的优势

Spring Boot会自动为您将POJO(普通的旧Java类)转换为JSON!

@RestController
public class HelloController {@RequestMapping("/")public ApiResponse home() {return new ApiResponse("SUCCESS", "hello");}
}public class ApiResponse {private String status;private String message;public ApiResponse(String status, String message) {this.status = status;this.message = message;}public String getStatus() {return status;}public String getMessage() {return message;}
}

执行: http -v localhost:8080

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Date: Tue, 14 Jun 2016 23:54:19 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked{"message": "hello","status": "SUCCESS"
}

3.对自动有线服务使用依赖注入

自动装配服务可以抽象出业务逻辑,而无需进行复杂的Java对象设置,配置或实例化。

@Service
public class HelloService {public String getGreeting(HttpServletRequest req) {String greeting = "World";Account account = AccountResolver.INSTANCE.getAccount(req);if (account != null) {greeting = account.getGivenName();}return greeting;}
}@RestController
public class HelloController {@AutowiredHelloService helloService;@RequestMapping("/")public ApiResponse home(HttpServletRequest req) {String greeting = helloService.getGreeting(req);return new ApiResponse("SUCCESS", "Hello " + greeting);}
}

一旦您通过身份验证,此示例将使用Stormpath返回个性化问候。 为此,您首先需要按照此处概述的方法设置一个Stormpath帐户。 如果您按照说明进行操作,并将Stormpath API密钥文件放在标准位置(~/.stormpath/apiKey.properties)则无需执行其他任何操作!

启动应用程序并执行以下命令: http -v localhost:8080

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Date: Wed, 15 Jun 2016 00:56:46 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked{"message": "Hello World","status": "SUCCESS"
}

接下来,我们需要进行身份验证,以便继续进行示例,因此,我们将使用Stormpath内置的OAuth 2.0功能来进行身份验证并获取个性化消息。 确保已在管理控制台中为Stormpath应用程序创建了一个用户。 有关Java SDK及其集成中Stormpath的OAuth支持的更多信息,请查看我们的Java产品文档

http -v -f POST localhost:8080/oauth/token \
Origin:http://localhost:8080 \
grant_type=password \
username=<email address of the user you setup> \
password=<password of the user you setup>

响应:

HTTP/1.1 200 OK
Cache-Control: no-store
Content-Length: 938
Content-Type: application/json;charset=UTF-8
Date: Wed, 15 Jun 2016 00:59:43 GMT
Pragma: no-cache
Server: Apache-Coyote/1.1{"access_token": "eyJraWQiOiJSOTJTQkhKQzFVNERBSU1HUTNNSE9HVk1YIiwic3R0IjoiYWNjZXNzIiwiYWxnIjoiSFMyNTYifQ.eyJqdGkiOiIzVFhQZ01Ld0NiQTk1VEp6VzBXTzRWIiwiaWF0IjoxNDY1OTUyMzgzLCJpc3MiOiJodHRwczovL2FwaS5zdG9ybXBhdGguY29tL3YxL2FwcGxpY2F0aW9ucy82dkZUNEFSZldDbXVIVlY4Vmt0alRvIiwic3ViIjoiaHR0cHM6Ly9hcGkuc3Rvcm1wYXRoLmNvbS92MS9hY2NvdW50cy8zcVlHbUl6VWh4UEtZTzI4a04wSWJSIiwiZXhwIjoxNDY1OTU1OTgzLCJydGkiOiIzVFhQZ0owckkwckFTZUU4SmtmN1NSIn0.o_pIHZVDZWogNuhJN2dmG4UKxACoWFxpRpp5OCyh6C4","expires_in": 3600,"refresh_token": "eyJraWQiOiJSOTJTQkhKQzFVNERBSU1HUTNNSE9HVk1YIiwic3R0IjoicmVmcmVzaCIsImFsZyI6IkhTMjU2In0.eyJqdGkiOiIzVFhQZ0owckkwckFTZUU4SmtmN1NSIiwiaWF0IjoxNDY1OTUyMzgzLCJpc3MiOiJodHRwczovL2FwaS5zdG9ybXBhdGguY29tL3YxL2FwcGxpY2F0aW9ucy82dkZUNEFSZldDbXVIVlY4Vmt0alRvIiwic3ViIjoiaHR0cHM6Ly9hcGkuc3Rvcm1wYXRoLmNvbS92MS9hY2NvdW50cy8zcVlHbUl6VWh4UEtZTzI4a04wSWJSIiwiZXhwIjoxNDcxMTM2MzgzfQ.mJBfCgv4Sdnw7Ubzup7CZ1xdAIC9iO31AJE3NMmp05E","token_type": "Bearer"
}

完成后,保存访问令牌以用于我们的应用程序:

ACCESS_TOKEN=eyJraWQiOiJSOTJTQkhKQzFVNERBSU1HUTNNSE9HVk1YIiwic3R0IjoiYWNjZXNzIiwiYWxnIjoiSFMyNTYifQ.eyJqdGkiOiIzVFhQZ01Ld0NiQTk1VEp6VzBXTzRWIiwiaWF0IjoxNDY1OTUyMzgzLCJpc3MiOiJodHRwczovL2FwaS5zdG9ybXBhdGguY29tL3YxL2FwcGxpY2F0aW9ucy82dkZUNEFSZldDbXVIVlY4Vmt0alRvIiwic3ViIjoiaHR0cHM6Ly9hcGkuc3Rvcm1wYXRoLmNvbS92MS9hY2NvdW50cy8zcVlHbUl6VWh4UEtZTzI4a04wSWJSIiwiZXhwIjoxNDY1OTU1OTgzLCJydGkiOiIzVFhQZ0owckkwckFTZUU4SmtmN1NSIn0.o_pIHZVDZWogNuhJN2dmG4UKxACoWFxpRpp5OCyh6C4

现在,让我们再次通过身份验证访问我们的应用程序:

http -v localhost:8080 Authorization:"Bearer $ACCESS_TOKEN"HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Date: Wed, 15 Jun 2016 01:05:35 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked{"message": "Hello Micah","status": "SUCCESS"
}

现在,由于依赖注入,我们从服务中获得了控制器可以访问的个性化响应。

4. Spring Security中的层

Spring Security在Spring应用程序中添加了一个授权层,这使得确定谁应该有权访问什么变得非常容易。 它使用声明性配置语法,并包含注释以限制谁可以访问基于组成员身份和细粒度权限的方法。

如果您想了解更多信息,我还编写了深入的Stormpath + Spring Security教程 。 我们还有一个很棒的教程,可以在开源Java SDK项目中将您从零带到功能完整的Spring Security + Spring Boot WebMVC应用程序 。 在此处找到教程文档。

默认情况下,所有内容都在Spring Security中被锁定,并且Stormpath Spring Security集成是遵循此约定的一个很好的例子。 要尝试使用带有Stormpath的Spring Security,您只需要在如下配置中应用Stormpath集成:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {http.apply(stormpath()).and().authorizeRequests().antMatchers("/").permitAll();}
}

http.apply(stormpath())是配置Stormpath Spring Security集成所需的全部。 接下来的两行允许未经授权的访问“/”端点。

让我们看一下这如何影响控制器中的方法:

@RequestMapping("/restricted")
public ApiResponse restricted(HttpServletRequest req) {// guaranteed to have account because of Spring Securityreturn new ApiResponse("SUCCESS", "Hello " + AccountResolver.INSTANCE.getAccount(req).getGivenName());
}

在这种情况下,无需对帐户执行null检查,因为我们知道,经过身份验证后,进入该方法的唯一方法。 例如:

http localhost:8080/restrictedHTTP/1.1 302 Found
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Wed, 15 Jun 2016 17:32:31 GMT
Expires: 0
Location: http://localhost:8080/login

由于我们未经身份验证,因此我们被重定向到/ login。 如果我像以前一样使用访问令牌,则如下所示:

http localhost:8080/restricted Authorization:"Bearer $ACCESS_TOKEN"HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
Date: Wed, 15 Jun 2016 17:34:34 GMT
Expires: 0
Pragma: no-cache{"message": "Hello Micah","status": "SUCCESS"
}

5.统一错误处理

良好的API设计表明,即使出现问题,您的API也会返回通用响应。 这使得将JSON解析和编组为Java对象变得更加容易和可靠。

让我们尝试一个例子。 在这里,我们需要一个标题: Custom-Header 。 如果该标头不存在,则会引发异常:

@RequestMapping("/custom-header")
public ApiResponse customHeader(HttpServletRequest req) throws MissingCustomHeaderException {String customHeader = req.getHeader("Custom-Header");if (customHeader == null) {throw new MissingCustomHeaderException("'Custom-Header' on the request is required.");}return new ApiResponse("SUCCESS", "Found Custom-Header: " + customHeader);
}

如果我们看“幸福的道路”,一切都很好:

http localhost:8080/custom-header \Custom-Header:MyCustomValue \Authorization:"Bearer $ACCESS_TOKEN"HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
Date: Wed, 15 Jun 2016 22:28:47 GMT{"message": "Found Custom-Header: MyCustomValue","status": "SUCCESS"
}

如果没有Custom-Header标头怎么办?

http localhost:8080/custom-header Authorization:"Bearer $ACCESS_TOKEN"HTTP/1.1 500 Internal Server Error
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: close
Content-Type: application/json;charset=UTF-8
Date: Wed, 15 Jun 2016 22:34:13 GMT{"error": "Internal Server Error","exception": "com.stormpath.spring.boot.examples.controller.HelloController$MissingCustomHeaderException","message": "'Custom-Header' on the request is required.","path": "/custom-header","status": 500,"timestamp": 1466030053360
}

那么,这怎么了? 首先,它不符合我们已经建立的响应格式。 另外,它还会导致500 (Internal Server Error)错误,这永远是不好的。

幸运的是,Spring Boot使此修复很容易。 我们需要做的就是添加一个异常处理程序。 无需其他代码更改。

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MissingCustomHeaderException.class)
public ApiResponse exception(MissingCustomHeaderException e) {return new ApiResponse("ERROR", e.getMessage());
}

现在让我们看一下响应:

http localhost:8080/custom-header Authorization:"Bearer $ACCESS_TOKEN"HTTP/1.1 400 Bad Request
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: close
Content-Type: application/json;charset=UTF-8
Date: Wed, 15 Jun 2016 22:59:32 GMT{"message": "'Custom-Header' on the request is required.","status": "ERROR"
}

现在我们有了正确的响应400 (Bad Request) 。 我们也有与成功回复相同格式的回复。

额外提示:尝试Stormpath

Stormpath提供了以开发人员为中心的高级身份服务,其中包括身份验证和授权,并且可以在几分钟内实现。 Stormpath REST API使开发人员可以快速轻松地构建他们自己必须编写的各种用户管理功能,包括:

  • 完善的授权支持 ,具有缓存功能,可实现最佳性能
  • 使用JSON Web令牌和OAuth2进行令牌身份验证和吊销
  • 对多租户应用程序的本机支持,以及对客户数据的预先构建的分区
  • 全面的文档和对客户服务的承诺-即使是免费的开发人员帐户
  • 健壮且惯用的SDK

建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!

立即注册按钮

翻译自: https://www.javacodegeeks.com/2016/10/5-practical-tips-building-spring-boot-api.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/351121.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++项目目录组织结构

项目目录结构的问题基本上是个仁者见仁&#xff0c;智者见智的问题&#xff0c;只要自己用着顺手&#xff0c;使用什么样的目录组织结构是没有什么大碍的。当然如果项目很大&#xff0c;参与的人员很多&#xff0c;那么合理的组织一下目录结构还是会有很大的益处的。不同类型的…

火绒杀毒软件更安静

https://www.huorong.cn/转载于:https://www.cnblogs.com/Tom-yi/p/10554564.html

完全编译安装boost

文章目录 1. 安装依赖2. 编译安装 boost3. 环境变量配置 boost是C世界中相当优秀的第三方库&#xff0c;被选入STL的也有不少&#xff0c;其中用到的C奇技淫巧更是数不胜数。 安装依赖 boost 在类 Unix 系统上的安装&#xff0c;可以参考官方文档的 Get Started&#xff0c;除此…

c#Md5 32位加密结果少了两个0的原因

我们的&#xff1a; e1adc3949ba59abbe56e57f20f883e 第三方的&#xff1a;e10adc3949ba59abbe56e057f20f883e 原因: 这个是很常见的错误&#xff0c;你字节转换成字符串的时候要保证是2位宽度啊&#xff0c;某个字节为0转换成字符串的时候必须是00的&#xff0c;否则就会丢失…

lambdas for_Wordcounter,使用Lambdas和Fork / Join计算Java中的单词数

lambdas for这些天来&#xff0c;我发布了Wordcounter &#xff0c;这是一个Java库和命令行实用程序&#xff0c;用于对文本文件中的单词进行计数并对单词计数进行分析&#xff0c;从而大量使用了功能编程结构和并行计算方法。 这是我在“令人讨厌的快速问答”大赛第四个条目SA…

Bitmap Font生成

工具&#xff1a;AngelCode 的 Bitmap Font Generator。把需要用到的文字写到一个txt&#xff0c;注意编码为Unicode。接着&#xff0c;在工具里 Edit->select chars from file选择刚才新建的txt文件。然后。。。之后的没啥细节&#xff0c;随意搞吧。转载于:https://www.cn…

分隔和截断字符串, boost string algorithm library中的split和trim

http://www.boost.org/doc/libs/1_46_1/doc/html/string_algo.html 这个库是个 headers only library  这个库提供了STL没有提供的 string-related算法, 但是实现做到了可以用在任何 character 的 container上 split 在写在线状态的改造时候要把一个字符串中描述的几种类型拆…

使用Spring Integration重试RabbitMQ

我最近阅读了有关使用RabbitMQ重试的方法 在这里&#xff0c;并想尝试类似的方法 Spring Integration &#xff0c;提供了一组很棒的集成抽象。 TL; DR解决的问题是重试一次消息&#xff08;在处理失败的情况下&#xff09;&#xff0c;两次重试之间有较大的延迟&#xff08…

Vue_(Router路由)-vue-router路由的基本用法

vue-router官网&#xff1a;传送门 vue-router起步&#xff1a;传送门 vue-router路由&#xff1a;Vue.js官网推出的路由管理器&#xff0c;方便的构建单页应用 单页应用&#xff1a;Single Page Application简称SPA&#xff0c;只有一个web页面的应用&#xff0c;用户与应用交…

利用boost做string到wstring转换,以及字符集转换

#include <boost/locale.hpp> int _tmain(int argc, _TCHAR* argv[]) {//std::locale::global(std::locale("utf-8"));std::locale::global(std::locale("")); // 设置全局的C运行库locale 可以针对cout fstream等单独设置 空表示默认使用当前系统…

P4198 楼房重建

[Luogu4198] 原题解 19.3.21 用线段树维护有关单调栈的问题 不要pushdown , 但是pushup的时候需要特别注意. 19.3.31 这里的\(pushup2\)其实就是几个特判 : 没有 , 直接返回当前区间答案 , 区间长度为\(1\) , 以及剩下两大类 , 这里有一个模板 : if(mx[ls]<tmp) return push…

Linux多线程实践(1) --线程理论

线程概念 在一个程序里的一个执行路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“一个进程内部的控制序列/指令序列”; 一切进程至少有一个执行线程; 进程 VS. 线程 1.进程是资源分配(进程需要参与资源的竞争)的基本单位,而线程是处理器调…

蓝桥杯 密文搜索(全排列)

题目描述福尔摩斯从X星收到一份资料&#xff0c;全部是小写字母组成。他的助手提供了另一份资料&#xff1a;许多长度为8的密码列表。福尔摩斯发现&#xff0c;这些密码是被打乱后隐藏在先前那份资料中的。请你编写一个程序&#xff0c;从第一份资料中搜索可能隐藏密码的位置。…

openshift_为Openshift + MongoDb应用程序编写验收测试

openshift验收测试用于确定是否满足规范要求。 它应在与生产环境尽可能相似的环境中运行。 因此&#xff0c;如果您的应用程序已部署到Openshift中&#xff0c;则您将需要一个与生产环境中使用的帐户平行的帐户&#xff0c;以运行测试。 在这篇文章中&#xff0c;我们将为部署到…

学 Win32 汇编[28] - 跳转指令: JMP、JECXZ、JA、JB、JG、JL、JE、JZ、JS、JC、JO、JP 等

跳转指令分三类:一、无条件跳转: JMP;二、根据 CX、ECX 寄存器的值跳转: JCXZ(CX 为 0 则跳转)、JECXZ(ECX 为 0 则跳转);三、根据 EFLAGS 寄存器的标志位跳转, 这个太多了.根据标志位跳转的指令: JE ;等于则跳转 JNE ;不等于则跳转JZ ;为 0 则跳转 JNZ ;不为 0 则跳转JS…

广告行业一些常用物料的尺寸

10-13 14:13 设计 /淘宝 海报 50cm 70cm &#xff08;宽 高&#xff09; 57cm 84cm &#xff08;宽 高&#xff09; 横幅 横幅尺寸高度默认为整10为单位&#xff0c;50、60、70、长度视环境而定&#xff0c;材料一般为牛津布&#xff0c;旗帜布&#xff0c;颜色有双色有彩…

Spring Security和自定义密码编码

在上一篇文章中&#xff0c;我们使用jdbc和md5密码编码将密码编码添加到了我们的spring安全配置中。 但是&#xff0c;在定制UserDetailsS​​ervices的情况下&#xff0c;我们需要对安全配置进行一些调整。 我们需要创建一个DaoAuthenticationProvider bean&#xff0c;并将…

智能变电站协议系列-2、SV/SMV协议示例(IEC61850)以及5G专网下的电力方案分析

文章目录 一、前言二、资料准备三、libiec61850的SV运行示例及抓包分析1、单独编译示例程序2、运行示例程序及5G专网场景下部署3、wireshark抓包分析 四、最后 一、前言 之前我们对IEC61850协议有了整体的了解&#xff0c;对一些概念有了一定的认识&#xff0c;并针对GOOSE协议…

php 常用的知识点归集(下)

24、静态属性与静态方法在类中的使用 需求&#xff1a;在玩CS的时候不停有伙伴加入&#xff0c;那么现在想知道共有多少人在玩&#xff0c;这个时候就可能用静态变量的方法来处理 利用原有的全局变量的方法来解决以上的问题 <?php header(content-type:text/html;charsetut…

GDB下查看内存命令(x命令)

可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示&#xff1a; x/<n/f/u> <addr> n、f、u是可选的参数。 n是一个正整数&#xff0c;表示需要显示的内存单元的个数&#xff0c;也就是说从当前地址向后显示几个内存单元的内容&#xff0c;一…