如何使用Spring设置安全的REST API

众所周知, Spring Boot是一个工具包,可以快速轻松地开发功能强大的Web服务。 它非常模块化,可以与其他框架和工具很好地配合使用。 在本教程中,我将向您展示通过使用Speedment作为ORM对现有SQL数据库设置RESTful API多么容易。

背景

Speedment是一个开放源代码工具包 ,它连接到数据库,分析元数据,并使用它生成实体和管理器类,以面向对象的方式对数据库进行建模。 它还包含一个运行时库,该库将Java 8 Streams转换为优化的SQL查询,使您可以使用非常类型安全和现代的方式编写代码。 事实证明,这对于Spring应用程序来说是完美的。

本教程的目标

本教程的目标是使用Spring开发REST API,该API会根据用户的角色授予对不同端点的访问权限。 如果您想向前看,可以在这里的指南中找到所有资源 。

POST /帐户 任何人都可以访问
GET /帐户/ {id} 可供管理员以及相关用户访问
GET /帐户 列出所有帐户,并且只有管理员可以访问

将使用我们将使用标准Java 8 Streams查询的MySQL数据库进行身份验证。 最后,我们将准备好一个完全面向对象的解决方案,可以使用自定义业务逻辑进行扩展!

如果您想跟随完成的项目,可以在GitHub上克隆它。

步骤1:数据库

为了简单起见,我使用的是使用以下语句创建的自定义MySQL数据库。 但是,您的想法是可以使用碰巧有权访问的任何现有数据库。

create database `securerest`;
use `securerest`;create table `account` (`id` bigint not null auto_increment primary key,`username` varchar(30) not null unique,`password` char(60) not null,`role` enum('USER', 'ADMIN') not null
);

步骤2:创建Maven项目

为了快速启动一个新的Spring项目,我推荐一个很棒的Spring Initializr网站。 在这里,您可以轻松输入项目所需的依赖项。

我们需要以下Spring依赖项:

  • spring-boot-starter-security
  • 弹簧启动启动器网站
  • MySQL的连接器的Java

其次,我们还需要添加Speedment依赖项以及Speedment插件来生成我们的代码。

<dependency><groupId>com.speedment</groupId><artifactId>runtime</artifactId><version>${speedment.version}</version><type>pom</type>
</dependency>
...
<plugin><groupId>com.speedment</groupId><artifactId>speedment-maven-plugin</artifactId><version>${speedment.version}</version><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version><scope>runtime</scope></dependency></dependencies>
</plugin>

步骤3:生成域模型

添加插件后,我们可以运行以下Maven目标来启动Speedment UI。

mvn speedment:tool

这将打开“加速工具”。 它将要求您提供数据库的用户名,密码,架构名称等。 输入字段的值,然后按“连接”。

在用户界面内,您可以执行许多配置。 您可以指定所生成代码的确切位置,禁用与应用程序无关的表或列,并在希望字段或表在代码中以其他形式出现时创建别名。

对于本教程,按“生成”就足够了。 现在,您应该看到如何在您的项目中生成许多新的Java类和包!

步骤4:配置Spring Security

为了允许Spring作为Spring Bean启动Speedment,我们需要指定实例的创建方式。 为此,我们创建一个名为SpeedmentConfiguration的类。

SpeedmentConfiguration.java

@Configuration
public class SpeedmentConfiguration {private @Value("${dbms.host}") String host;private @Value("${dbms.port}") int port;private @Value("${dbms.schema}") String schema;private @Value("${dbms.username}") String username;private @Value("${dbms.password}") String password;@Beanpublic SpeedmentApplication getSpeedmentApplication() {return new SpeedmentApplicationBuilder().withIpAddress(host).withPort(port).withUsername(username).withPassword(password).withSchema(schema).build();}@Beanpublic AccountManager getAccountManager(SpeedmentApplication app) {return app.getOrThrow(AccountManager.class);}
}

默认情况下,顶部的@Value字段是从名为application.properties的文件加载的。 因此,我们应该在此处指定值:

application.properties

# Speedment Settings
dbms.host=localhost
dbms.port=3306
dbms.schema=securerest
dbms.username=root
dbms.password=password# Server Settings
server.port=9777

接下来,我们需要创建用于用户身份验证的配置类。 我们称此类为AuthenticationConfiguration。

AuthenticationConfiguration.java

@Configuration
public class AuthenticationConfiguration 
extends GlobalAuthenticationConfigurerAdapter {private @Autowired AccountManager accounts;@Beanpublic DaoAuthenticationProvider authProvider() {final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();authProvider.setUserDetailsService(getUserDetailsService());authProvider.setPasswordEncoder(getPasswordEncoder());return authProvider;}@Beanpublic UserDetailsService getUserDetailsService() {return username -> accounts.stream().filter(Account.USERNAME.equal(username)).findAny().orElseThrow(() -> new UsernameNotFoundException("Could not find the user '" + username + "'"));}@Beanpublic PasswordEncoder getPasswordEncoder() {return new BCryptPasswordEncoder();}@Overridepublic void init(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(getUserDetailsService()).passwordEncoder(getPasswordEncoder());}
}

注意我们如何在生成的AccountManager上使用@Autowired,因为它在SpeedmentConfiguration类中被指定为Spring Bean。

在方法getUserDetailsS​​ervice()中,我们将Stream API与自定义谓词一起使用,从而允许将流转换为优化的SQL查询。 但是,要使此方法起作用,我们需要做一件事。 我们需要确保生成的Account接口扩展了UserDetails,以便可以与Spring API无缝使用。 这很容易做到,因为Speedment不会覆盖不是以“ Generated”开头的文件。

Account.java

public interface Account extends GeneratedAccount, UserDetails {}

我们还需要在实现类中添加一些方法来支持该接口。

AccountImpl.java

@JsonIgnoreProperties("password")
public final class AccountImpl extends GeneratedAccountImpl 
implements Account {private static final long serialVersionUID = -7552975849070084309L;@Override @JsonIgnorepublic Collection<? extends GrantedAuthority> getAuthorities() {return createAuthorityList(getRole());}@Override @JsonIgnorepublic boolean isAccountNonExpired() {return true;}@Override @JsonIgnorepublic boolean isAccountNonLocked() {return true;}@Override @JsonIgnorepublic boolean isCredentialsNonExpired() {return true;}@Override @JsonIgnorepublic boolean isEnabled() {return true;}
}

然后,我们创建第三个配置文件,以定义访问各种REST端点所需的权限。

SecurityConfiguration.java

@Configuration
@EnableWebSecurity
public class SecurityConfiguration 
extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers(POST, "/account").permitAll().antMatchers(GET, "/account").hasAuthority("ROLE_ADMIN").anyRequest().fullyAuthenticated().and().httpBasic().and().csrf().disable();}
}

步骤5:创建控制器

最后一步是在我们的业务逻辑所在的位置创建Controller类。 该类带有@RestController批注,以允许Spring自动拾取它。 它定义了三个映射,每个REST端点一个。

AccountController.java

@RestController
public class AccountController {private @Autowired AccountManager accounts;private @Autowired PasswordEncoder passwordEncoder;...}

第一个端点是注册命令。 它将位于“ POST /帐户”上。 我们使用两个参数,用户名和密码,对密码进行哈希处理,然后将其持久保存到数据库中。 如果用户名已经存在,则该操作将失败,因为用户名在数据库中被定义为UNIQUE。

@PostMapping("/account")long onPostAccount(@RequestParam("username") String username,@RequestParam("password") String password) {final Account created = accounts.persist(new AccountImpl().setUsername(username).setPassword(passwordEncoder.encode(password)).setRole("USER"));return created.getId();}

接下来是“ GET / account”端点。 这很简单。 我们将使用生成的管理器类启动流。 然后,通过Speedment将流优化为SQL查询。

@GetMapping("/account")List<Account> onGetAllAccounts() {return accounts.stream().collect(toList());}

最后一个端点要复杂一些。 我们将Spring配置为仅允许登录的用户访问“ GET / account {id}”,但是我们要确保用户只能访问自己的信息,除非他们具有“ ADMIN”角色。

@GetMapping("/account/{id}")Account onGetAccount(@PathVariable("id") long accountId,Authentication auth) {final Account account = (Account) auth.getPrincipal();if (account.getId() == accountId) {return account;} else if ("ADMIN".equals(account.getRole())) {return accounts.stream().filter(Account.ID.equal(accountId)).findAny().orElseThrow(NotFoundException::new);} else {throw new ForbiddenException();}}

做完了! 现在,我们有了一个REST API,它使用数据库来存储用户并使用基本身份验证来确保用户只能调用他们有权访问的命令!

尝试一下

要尝试我们刚刚创建的REST API,只需启动一个终端并使用cURL命令即可!

要注册帐户:

curl -X POST "http://localhost:9777/account?username=my_user&password=my_pass"

要查看我们自己的信息(在这种情况下,我们是ID为1的用户):

curl -X  GET -u my_user:my_pass "http://localhost:9777/account/1"

列出所有用户(需要ADMIN角色):

curl -X GET -u my_user:my_pass "http://localhost:9777/account"

摘要

在本教程中,我们创建了一个新的Spring Boot项目,以使用简单的注册系统快速映射RESTful API,并使用Speedment为该API生成面向对象的数据库访问层。 我们还配置了Spring Security来要求用户进行身份验证以访问特定的端点。

有关如何使用Speedment的更多指南和教程, 请查看GitHub页面 ! 您还可以在其中找到一些示例项目,这些示例项目说明了如何使用Speedment中提供的更多出色的代码生成功能!

可以在这里找到本教程的完整资源!

直到下一次!

翻译自: https://www.javacodegeeks.com/2017/03/set-secure-rest-api-spring.html

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

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

相关文章

OpenCV imread()函数

imread&#xff08;const string& filename, int flags1&#xff09; 例如&#xff1a; //读入图像单通道&#xff0c;即灰度图 ScrImage imread("C:\\Users\\Desktop\\opencv_1.jpg", 0);imread函数从文件中加载图像并返回该图像。如果该图像不能被读取&#x…

layui横向时间线_炒股一生只买一种股票:股价K线形成这样后,必然有一波拉升...

在上升趋势中做多; 在下跌趋势中做空; 在震荡区间顶部做空、底部做多。大趋势像是遛狗的主人&#xff0c;他走的比较慢&#xff1b;狗就像中短期的走势&#xff0c;活蹦乱跳&#xff0c;有时候跑过头&#xff0c;又会回来找主人一下&#xff0c;然后再去东闻闻、西嗅嗅。最后你…

最小二乘

1.最小二乘的背景 这种东东的来源&#xff0c;比较容易找到而且比较靠谱的途径自然是wiki百科了&#xff0c;以下部分的内容来自wiki百科&#xff1a; 1801年&#xff0c;意大利天文学家朱赛普皮亚齐发现了第一颗小行星谷神星。经过40天的跟踪观测后&#xff0c;由于谷神星运…

团队冲刺计划第八天

1、 所有工作的预期时间&#xff1a;96h 目前已经花的时间:78h 还剩余的时间:18h 2、任务看板 3、冲刺会议照片&#xff1a; 4、燃尽图&#xff1a; 转载于:https://www.cnblogs.com/532BEST/p/10871189.html

[Linux]Linux下经常会用到的简单实例(持续更新)

1、查找某些进程并结束他们&#xff1a; ps -elf | grep 进程关键字 | awk {print $4}| xargs kill -9 解析&#xff1a; ps -elf 的 -e 代表列出所有进程&#xff0c;-l 代表长格式&#xff0c;-f 代表完整的格式 grep的工作方式是这样的&#xff0c;它在一个或多个文件中搜索…

elupload获取文件名与路径_Uipath获取文件名,路径,扩展名等操作

Uipath获取文件名&#xff0c;路径&#xff0c;扩展名等操作东京IT青年前线​www.rpatokyo.com使用Assign Activity&#xff0c;声明一个字符串变量为str获取文件路径代码System.IO.Path.GetDirectoryName(“C:UsersAdministratorDesktop备课二回目css基础.pptx”)运行&#xf…

servlet3.0新特性_查看Servlet 3.0的新增功能

servlet3.0新特性随着JEE6规范上市&#xff0c;在企业应用程序领域中如何开发应用程序方面发生了一些重大变化。 在本文中&#xff0c;我将介绍有关Web应用程序开发的一些更改。 首先&#xff0c;请告别web.xml部署描述符&#xff08;至少是其中的一部分&#xff09;。 好吧&am…

Android(2)-----Fragment //(第七周后的知识)

1、Fragmentandroid.app.Fragment版本&#xff1a;//v4版本是为了由3.0向下兼容到1.6&#xff0c;改那个Fragment文件里的import android.support.v4.app.Fragment;换成 import android.app.Fragment;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01…

延迟加载是一种代码气味

您见过那些具有许多属性的巨大物体吗&#xff1f; 这些域对象由于不希望从数据库检索太多信息而在其中使用延迟加载&#xff1f; 我敢打赌你有这种令人怀疑的快乐。 今天&#xff0c;我想与大家分享我对它们的印象- 使用延迟加载应该被视为一种代码味道&#xff01; 让我解释…

c#时间函数

我们可以通过使用DataTime这个类来获取当前的时间。通过调用类中的各种方法我们可以获取不同的时间&#xff1a;如&#xff1a;日期&#xff08;2008-09-04&#xff09;、时间&#xff08;12&#xff1a;12&#xff1a;12&#xff09;、日期时间&#xff08;2008-09-04 12&…

gbk编码在线转换工具_TOOLFK工具-在线汉字/字母/人民币/简繁体转换工具

本文要推荐的[TOOLFK]在线汉字/字母/人民币/简繁体转换工具,提供简繁体在线转换、人民币大写转换、字母大小写互转、汉字转拼音在线日常使用工具。網站名稱&#xff1a;ToolFk網站鏈結&#xff1a;https://www.toolfk.com/工具链接&#xff1a;https://www.toolfk.com/tool-onl…

hive的metatable学习

一、存储Hive版本的元数据表&#xff08;VERSION&#xff09; &#xfffc; &#xfffc; 二、Hive数据库相关的元数据表&#xff08;DBS、DATABASE_PARAMS&#xff09; DBS --存储Hive中所有数据库的基本信息 &#xfffc; &#xfffc; DATABASE_PARAMS --该表存储数据库的相…

clickhouse官方文档_clickhouse分析:结合grafana和metabase完成监控和数据分析

点击上方蓝字关注我们“ 关于clickhouse的监控和可视化界面&#xff0c;想必刚接触到ch的人是一头雾水&#xff0c;大厂往往会给ch集群定制各种监控和可视化分析&#xff0c;普通用户就需要我们自己寻求现成的开源工具&#xff0c;在一些常见的开源工具上&#xff0c;我们可以较…

hazelcast_带弹簧的Hazelcast分布式执行

hazelcastExecutorService功能是Java 5附带的&#xff0c;位于java.util.concurrent包中。 它扩展了Executor接口&#xff0c;并提供了线程池功能来执行异步简短任务。 建议使用Java Executor服务类型来查看基本的ExecutorService实现。 ThreadPoolExecutor也是ExecutorServic…

OpenCV测试程序

#include<opencv2\opencv.hpp> using namespace cv; int main() {Mat picture imread("1.jpg");//图片必须添加到工程目下//也就是和test.cpp文件放在一个文件夹下&#xff01;&#xff01;&#xff01;imshow("测试程序", picture);waitKey(201509…

Java中的do-while循环——通过示例学习Java编程(11)

作者&#xff1a;CHAITANYA SINGH 来源&#xff1a;https://www.koofun.com/pro/kfpostsdetail?kfpostsid22&cid0 在上一篇教程中&#xff0c;我们讨论了while循环。在本教程中&#xff0c;我们将讨论java中的do-while循环。do-while循环类似于while循环&#xff0c;但是它…

centos7离线安装mysql_Centos7离线安装metasploit详细教程

最近需在内网服务器搭建安全工具环境&#xff0c;苦于内网服务器无法访问互联网&#xff0c;需要很多依赖包比较麻烦&#xff0c;尤其metasploit无互联网安装特别麻烦&#xff0c;而且网上metasploit的安装教程均是在线一键安装教程&#xff0c;对于无法访问互联网的服务器进行…

净资产的结构

Netty的包装结构很棒。 每个程序员都应该研究它。 每个系统都应该模仿它&#xff1b; 每个项目经理都应将其打印出来&#xff0c;拍在墙上&#xff0c;然后对开发人员说&#xff1a;“那样。” Netty是一个“……用于快速开发可维护的高性能协议服务器和客户端的异步事件驱动…

常用的HTTP响应头

响应头 说明 示例 状态 Access-Control-Allow-Origin 指定哪些网站可以跨域源资源共享 Access-Control-Allow-Origin: * 临时 Accept-Patch 指定服务器所支持的文档补丁格式 Accept-Patch: text/example;charsetutf-8 固定 Accept-Ranges 服务器所支持的内容范围 …

iframe嵌入页面白屏_封闭在家学网页制作!为页面嵌入PDF文件——零基础自学网页制作

在页面中嵌入PDF文件在上一篇《在html页面中嵌入其他页面的方法——零基础自学网页制作》(结尾见目录)中我们学习了如何在页面中嵌入其他页面的操作。今天我们来嵌入一个pdf文件。其实使用示例代码如下&#xff1a;页面效果如下&#xff1a;考虑到pdf的版权问题就不给大家上传云…