Last active
November 5, 2021 13:21
-
-
Save petrabarus/22ad66f6a0768ace91335bc58eb439f3 to your computer and use it in GitHub Desktop.
Part 3 Using DynamoDB for Session Management in PHP/Yii2 Application
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
version: '3' | |
services: | |
php: | |
build: . | |
volumes: | |
- ~/.composer-docker/cache:/root/.composer/cache:delegated | |
- ./:/app:delegated | |
ports: | |
- '8080:80' | |
environment: | |
AWS_REGION: 'ap-southeast-1' | |
AWS_ACCESS_KEY_ID: 'fake-access-key' | |
AWS_SECRET_ACCESS_KEY: 'fake-secret-key' | |
DYNAMODB_SESSION_TABLE_NAME: 'Sessions' | |
DYNAMODB_ENDPOINT_URL: 'http://localstack:4569' | |
depends_on: | |
- localstack | |
localstack: | |
image: localstack/localstack | |
volumes: | |
- ./bin/localstack-setup.sh:/localstack-setup.sh | |
ports: | |
- "4569:4569" | |
environment: | |
SERVICES: 'dynamodb' | |
DEFAULT_REGION: 'ap-southeast-1' | |
AWS_REGION: 'ap-southeast-1' | |
AWS_ACCESS_KEY_ID: 'fake-access-key' | |
AWS_SECRET_ACCESS_KEY: 'fake-secret-key' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# file: /bin/localstack-setup.sh | |
echo "Setting Up..." | |
aws --endpoint-url=http://localhost:4569 \ | |
--region=$AWS_REGION \ | |
dynamodb \ | |
create-table --table-name Sessions \ | |
--attribute-definitions AttributeName=id,AttributeType=S \ | |
--key-schema AttributeName=id,KeyType=HASH \ | |
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \ | |
1> /dev/null | |
aws --endpoint-url=http://localstack:4569 \ | |
--region=$AWS_REGION \ | |
dynamodb list-tables |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//file: /components/Session.php | |
namespace app\components; | |
use yii\web\Session as BaseSession; | |
use Aws\DynamoDb\DynamoDbClient; | |
class Session extends BaseSession { | |
private $client; | |
public $clientConfigs = []; | |
public $sessionConfigs = []; | |
public function init() | |
{ | |
$this->createDynamoDbClient(); | |
parent::init(); | |
} | |
protected function registerSessionHandler() | |
{ | |
$configs = array_filter($this->sessionConfigs); | |
$this->handler = $this->client->registerSessionHandler($configs); | |
parent::registerSessionHandler(); | |
} | |
private function createDynamoDbClient() | |
{ | |
$configs = array_filter($this->clientConfigs); | |
$this->client = new DynamoDbClient($configs); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//file /controllers/TestController.php | |
namespace app\controllers; | |
use Yii; | |
use yii\web\Controller; | |
class TestController extends Controller { | |
public function actionIndex($name = '') { | |
$sessionId = Yii::$app->session->id; | |
if (!empty($name)) { | |
Yii::$app->session->set('name', $name); | |
} | |
$name = Yii::$app->session->get('name'); | |
return "My name is {$name}. My session ID is: {$sessionId}"; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
//file: /config/web.php | |
$params = require __DIR__ . '/params.php'; | |
$db = require __DIR__ . '/db.php'; | |
$config = [ | |
'id' => 'basic', | |
'basePath' => dirname(__DIR__), | |
'bootstrap' => ['log'], | |
'aliases' => [ | |
'@bower' => '@vendor/bower-asset', | |
'@npm' => '@vendor/npm-asset', | |
], | |
'components' => [ | |
'request' => [ | |
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation | |
'cookieValidationKey' => 'dFq59wCiBJbanLg794ATD34bQNZIrCLf', | |
], | |
'cache' => [ | |
'class' => 'yii\caching\FileCache', | |
], | |
'user' => [ | |
'identityClass' => 'app\models\User', | |
'enableAutoLogin' => true, | |
], | |
'errorHandler' => [ | |
'errorAction' => 'site/error', | |
], | |
'mailer' => [ | |
'class' => 'yii\swiftmailer\Mailer', | |
// send all mails to a file by default. You have to set | |
// 'useFileTransport' to false and configure a transport | |
// for the mailer to send real emails. | |
'useFileTransport' => true, | |
], | |
'log' => [ | |
'traceLevel' => YII_DEBUG ? 3 : 0, | |
'targets' => [ | |
[ | |
'class' => 'yii\log\FileTarget', | |
'levels' => ['error', 'warning'], | |
], | |
], | |
], | |
'db' => $db, | |
'urlManager' => [ | |
'enablePrettyUrl' => true, | |
'showScriptName' => false, | |
'rules' => [ | |
], | |
], | |
'session' => [ | |
'class' => app\components\Session::class, | |
'clientConfigs' => [ | |
'version' => '2012-08-10', | |
'region' => $_ENV['AWS_REGION'], | |
'endpoint' => $_ENV['DYNAMODB_ENDPOINT_URL'] ?? null | |
], | |
'sessionConfigs' => [ | |
'table_name' => $_ENV['DYNAMODB_SESSION_TABLE_NAME'] | |
] | |
] | |
], | |
'params' => $params, | |
]; | |
if (YII_ENV_DEV) { | |
// configuration adjustments for 'dev' environment | |
$config['bootstrap'][] = 'debug'; | |
$config['modules']['debug'] = [ | |
'class' => 'yii\debug\Module', | |
// uncomment the following to add your IP if you are not connecting from localhost. | |
//'allowedIPs' => ['127.0.0.1', '::1'], | |
]; | |
$config['bootstrap'][] = 'gii'; | |
$config['modules']['gii'] = [ | |
'class' => 'yii\gii\Module', | |
// uncomment the following to add your IP if you are not connecting from localhost. | |
//'allowedIPs' => ['127.0.0.1', '::1'], | |
]; | |
} | |
return $config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//file /cdk/webapp.ts | |
import cdk = require('@aws-cdk/core'); | |
import ecs = require("@aws-cdk/aws-ecs"); | |
import ecsPatterns = require("@aws-cdk/aws-ecs-patterns"); | |
import ecr = require('@aws-cdk/aws-ecr'); | |
import dynamodb = require('@aws-cdk/aws-dynamodb') | |
import { Cluster } from './cluster'; | |
interface WebAppProps { | |
readonly cluster: Cluster; | |
} | |
class WebApp extends cdk.Construct { | |
private fargateService: ecsPatterns.ApplicationLoadBalancedFargateService; | |
private sessionTable: dynamodb.Table; | |
public readonly service: ecs.IBaseService; | |
public readonly containerName: string; | |
public readonly ecrRepo: ecr.Repository; | |
constructor(scope: cdk.Construct, id: string, props: WebAppProps) { | |
super(scope, id); | |
this.ecrRepo = new ecr.Repository(this, 'ECRRepo'); | |
this.sessionTable = this.createSessionTable(); | |
this.fargateService = this.createService(props.cluster.ecsCluster); | |
this.service = this.fargateService.service; | |
this.containerName = this.fargateService.taskDefinition.defaultContainer!.containerName; | |
this.grantPermissions(); | |
this.addAutoScaling(); | |
this.output(); | |
} | |
private createService(cluster: ecs.Cluster) { | |
const region = cdk.Stack.of(this).region; | |
return new ecsPatterns.ApplicationLoadBalancedFargateService(this, 'Service', { | |
cluster: cluster, | |
taskImageOptions: { | |
image: ecs.ContainerImage.fromAsset('.'), | |
environment: { | |
AWS_REGION: region, | |
DYNAMODB_SESSION_TABLE_NAME: this.sessionTable.tableName, | |
} | |
}, | |
}); | |
} | |
private addAutoScaling() { | |
const autoScalingGroup = this.fargateService.service.autoScaleTaskCount({ | |
minCapacity: 2, | |
maxCapacity: 10 | |
}); | |
autoScalingGroup.scaleOnCpuUtilization('CpuScaling', { | |
targetUtilizationPercent: 50, | |
scaleInCooldown: cdk.Duration.seconds(60), | |
scaleOutCooldown: cdk.Duration.seconds(60), | |
}); | |
} | |
private createSessionTable(): dynamodb.Table { | |
return new dynamodb.Table(this, 'Sessions', { | |
partitionKey: { | |
name: 'id', | |
type: dynamodb.AttributeType.STRING, | |
} | |
}); | |
} | |
private grantPermissions() { | |
const taskDefinition = this.fargateService.taskDefinition; | |
this.ecrRepo.grantPull(taskDefinition.executionRole!); | |
const actions = [ | |
"dynamodb:GetItem", | |
"dynamodb:UpdateItem", | |
"dynamodb:DeleteItem", | |
"dynamodb:Scan", | |
"dynamodb:BatchWriteItem" | |
] | |
this.sessionTable.grant(taskDefinition.taskRole, ...actions); | |
} | |
private output() { | |
new cdk.CfnOutput(this, 'ECRRepoURI', {value: this.ecrRepo.repositoryUri}); | |
new cdk.CfnOutput(this, 'ServiceName', {value: this.service.serviceName}); | |
new cdk.CfnOutput(this, 'ContainerName', {value: this.containerName}); | |
new cdk.CfnOutput(this, 'SessionTableName', {value: this.sessionTable.tableName}); | |
} | |
} | |
export {WebApp, WebAppProps}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
would using dynamodb solve this issue? yiisoft/yii2-authclient#324