Java数据库应用原型

2025-12-12 0 260

在工作中开发时,我多次需要一个简单应用的模板,以便基于此模板开始为手头的项目添加特定代码。

在本文中,我将创建一个简单的 Java 应用程序,它连接到数据库,暴露一些 REST 端点,并使用基于角色的访问来保护这些端点。

目的是拥有一个最小化且功能齐全的应用程序,然后可以针对特定任务进行定制。

对于数据库,我们将使用 PostgreSQL;对于安全,我们将使用 Keycloak,两者都通过容器部署。在开发过程中,我使用 podman 来测试容器是否正确创建(作为 docker 的替代品——它们在大多数情况下可以互换)作为一次学习体验。

应用程序本身是使用 Spring Boot 框架开发的,并使用 Flyway 进行数据库版本管理。

所有这些技术都是 Java EE 领域业界标准,在项目中被使用的可能性很高。

我们构建原型的核心需求是一个图书馆应用程序,它暴露 REST 端点,允许创建作者、书籍以及它们之间的关系。这将使我们能够实现一个多对多关系,然后可以将其扩展用于任何可以想象的目的。

完整可用的应用程序可以在 github.com/ghalldev/db… 找到。

本文中的代码片段取自该代码库

在创建容器之前,请确保使用您偏好的值定义以下环境变量(教程中故意省略了它们,以避免传播多个用户使用的默认值):


DOCKER_POSTGRES_PASSWORD

DOCKER_KEYCLOAK_ADMIN_PASSWORD

DOCKER_GH_USER1_PASSWORD

配置 PostgreSQL:


docker container create --name gh_postgres --env POSTGRES_PASSWORD=$DOCKER_POSTGRES_PASSWORD --env POSTGRES_USER=gh_pguser --env POSTGRES_INITDB_ARGS=--auth=scram-sha-256 --publish 5432:5432 postgres:17.5-alpine3.22

docker container start gh_postgres

配置 Keycloak:

首先是容器的创建并启动:


docker container create --name gh_keycloak --env DOCKER_GH_USER1_PASSWORD=$DOCKER_GH_USER1_PASSWORD --env KC_BOOTSTRAP_ADMIN_USERNAME=gh_admin --env KC_BOOTSTRAP_ADMIN_PASSWORD=$DOCKER_KEYCLOAK_ADMIN_PASSWORD --publish 8080:8080 --publish 8443:8443 --publish 9000:9000 keycloak/keycloak:26.3 start-dev

docker container start gh_keycloak

在容器启动并运行后,我们可以继续创建领域、用户和角色(这些命令必须在正在运行的容器内部执行):


cd $HOME/bin

./kcadm.sh config credentials --server http://localhost:8080 --realm master --user gh_admin --password $KC_BOOTSTRAP_ADMIN_PASSWORD

./kcadm.sh create realms -s realm=gh_realm -s enabled=true

./kcadm.sh create users -s username=gh_user1 -s email=\"gh_user1@email.com\" -s firstName=\"gh_user1firstName\" -s lastName=\"gh_user1lastName\" -s emailVerified=true -s enabled=true -r gh_realm

./kcadm.sh set-password -r gh_realm --username gh_user1 --new-password $DOCKER_GH_USER1_PASSWORD

./kcadm.sh create roles -r gh_realm -s name=viewer -s \'description=Realm role to be used for read-only features\'

./kcadm.sh add-roles --uusername gh_user1 --rolename viewer -r gh_realm

./kcadm.sh create roles -r gh_realm -s name=creator -s \'description=Realm role to be used for create/update features\'

./kcadm.sh add-roles --uusername gh_user1 --rolename creator -r gh_realm

ID_ACCOUNT_CONSOLE=$(./kcadm.sh get clients -r gh_realm --fields id,clientId | grep -B 1 \'\"clientId\" : \"account-console\"\' | grep -oP \'[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}\')

./kcadm.sh update clients/$ID_ACCOUNT_CONSOLE -r gh_realm -s \'fullScopeAllowed=true\' -s \'directAccessGrantsEnabled=true\'

用户 gh_user1 在领域 gh_realm 中被创建,并拥有 viewercreator 角色。

您可能已经注意到,我们没有创建新的客户端,而是使用了 Keycloak 自带的一个默认客户端:account-console。这是为了方便起见,在实际场景中,您会创建一个特定的客户端,然后将其更新为具有 fullScopeAllowed(这会导致领域角色被添加到令牌中——默认情况下不添加)和 directAccessGrantsEnabled(允许通过 Keycloak 的 openid-connect/token 端点生成令牌,在我们的例子中使用 curl)。

创建的角色随后可以在 Java 应用程序内部使用,以根据我们约定的契约来限制对某些功能的访问——viewer 只能访问只读操作,而 creator 可以执行创建、更新和删除操作。当然,同样地,可以根据任何原因创建各种角色,只要约定的契约被明确定义并被所有人理解。

角色还可以进一步添加到组中,但本教程不包含这部分内容。

但是,在实际使用这些角色之前,我们必须告诉 Java 应用程序如何提取角色——这是必须的,因为 Keycloak 将角色添加到 JWT 的方式是其特有的,所以我们必须编写一段自定义代码,将其转换为 Spring Security 可以使用的东西:


@Bean

public JwtAuthenticationConverter jwtAuthenticationConverter() {

// 遵循与 org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter 相同的模式

Converter<Jwt, Collection> keycloakRolesConverter = new Converter() {

private static final String DEFAULT_AUTHORITY_PREFIX = \"ROLE_\";

//https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java#L901

private static final String KEYCLOAK_REALM_ACCESS_CLAIM_NAME = \"realm_access\";

private static final String KEYCLOAK_REALM_ACCESS_ROLES = \"roles\";

  


@Override

public Collection convert(Jwt source) {

Collection grantedAuthorities = new ArrayList();

Map<String, List> realmAccess = source.getClaim(KEYCLOAK_REALM_ACCESS_CLAIM_NAME);

if (realmAccess == null) {

logger.warn(\"No \" + KEYCLOAK_REALM_ACCESS_CLAIM_NAME + \" present in the JWT\");

return grantedAuthorities;

}

List roles = realmAccess.get(KEYCLOAK_REALM_ACCESS_ROLES);

if (roles == null) {

logger.warn(\"No \" + KEYCLOAK_REALM_ACCESS_ROLES + \" present in the JWT\");

return grantedAuthorities;

}

roles.forEach(

role -> grantedAuthorities.add(new SimpleGrantedAuthority(DEFAULT_AUTHORITY_PREFIX + role)));

  


return grantedAuthorities;

}

  


};

JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();

jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(keycloakRolesConverter);

  


return jwtAuthenticationConverter;

}

AppConfiguration 类中还完成了其他重要配置,例如启用方法安全性和禁用 CSRF。

现在我们可以在 REST 控制器中使用 @org.springframework.security.access.prepost.PreAuthorize 注解来限制访问:


@PostMapping(\"/author\")

@PreAuthorize(\"hasRole(\'creator\')\")

public void addAuthor(@RequestParam String name, @RequestParam String address) {

authorService.add(new AuthorDto(name, address));

}

  


@GetMapping(\"/author\")

@PreAuthorize(\"hasRole(\'viewer\')\")

public String getAuthors() {

return authorService.allInfo();

}

通过这种方式,只有成功通过身份验证且拥有 hasRole 中列出的角色的用户才能调用端点,否则他们将收到 HTTP 403 Forbidden 错误。

在容器启动并配置完成后,Java 应用程序可以启动了,但在启动之前需要添加数据库密码——这可以通过环境变量完成(下面是一个 Linux shell 示例):


export SPRING_DATASOURCE_PASSWORD=$DOCKER_POSTGRES_PASSWORD

现在,如果一切正常启动并运行,我们可以使用 curl 来测试我们的应用程序(以下所有命令均为 Linux shell 命令)。

使用之前创建的用户 gh_user1 登录并提取身份验证令牌:


KEYCLOAK_ACCESS_TOKEN=$(curl -d \'client_id=account-console\' -d \'username=gh_user1\' -d \"password=$DOCKER_GH_USER1_PASSWORD\" -d \'grant_type=password\' \'http://localhost:8080/realms/gh_realm/protocol/openid-connect/token\' | grep -oP \'\"access_token\":\"K[^\"]*\')

创建一个新作者(这将测试 creator 角色是否有效):


curl -X POST --data-raw \'name=\"GH_name1\"&address=\"GH_address1\"\' -H \"Authorization: Bearer $KEYCLOAK_ACCESS_TOKEN\" \'localhost:8090/library/author\'

检索库中的所有作者(这将测试 viewer 角色是否有效):


curl -X GET -H \"Authorization: Bearer $KEYCLOAK_ACCESS_TOKEN\" \'localhost:8090/library/author\'

至此,您应该拥有了创建自己的 Java 应用程序所需的一切,可以根据需要对其进行扩展和配置。


【注】本文译自:Java Spring Boot Template With PostgreSQL, Keycloak Securit

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 Java数据库应用原型 https://www.zuozi.net/35764.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务