How to Implement Session Timeout in play framework 2.2.5? - session-timeout

We want to implement session timeout for 10m in our play web application. But I have no idea on how to do this. I followed play 2.2.x documentation and some other web sites's like below mentioned. But it doesn't works for me, how do I do this?
Secured.java:
#Override
public String getUsername(Http.Context ctx) {
// see if user is logged in
if (session("userId") == null)
return null;
// see if the session is expired
String previousTick = session("userTime");
if (previousTick != null && !previousTick.equals("")) {
long previousT = Long.valueOf(previousTick);
long currentT = new Date().getTime();
long timeout = Long.valueOf(Play.application().configuration().getString("sessionTimeout")) * 1000 * 60;
if ((currentT - previousT) > timeout) {
// session expired
session().clear();
return null;
}
}
// update time in session
String tickString = Long.toString(new Date().getTime());
session("userTime", tickString);
return User.findById(Long.parseLong(session("userId"))).getUsername();
}
application.conf :
sessionTimeout=10

Finally, I figure out above issue. #Security.Authenticated(Secured.class) in controller class was missed.

Related

The connection was inactive for more than the allowed 60000 milliseconds and is closed by container

I have an azure function that sends a message to the service bus queue. Since a recent deployment, I see an exception occurring frequently: The connection was inactive for more than the allowed 60000 milliseconds and is closed by container.
I looked into this GitHub post: https://github.com/Azure/azure-service-bus-java/issues/280 it says this is a warning. Is there a way to increase this timeout? Or any suggestions on how to resolve this? Here is my code:
namespace Repositories.ServiceBusQueue
{
public class MembershipServiceBusRepository : IMembershipServiceBusRepository
{
private readonly QueueClient _queueClient;
public MembershipServiceBusRepository(string serviceBusNamespacePrefix, string queueName)
{
var msiTokenProvider = TokenProvider.CreateManagedIdentityTokenProvider();
_queueClient = new QueueClient($"https://{serviceBusNamespacePrefix}.servicebus.windows.net", queueName, msiTokenProvider);
}
public async Task SendMembership(GroupMembership groupMembership, string sentFrom = "")
{
if (groupMembership.SyncJobPartitionKey == null) { throw new ArgumentNullException("SyncJobPartitionKey must be set."); }
if (groupMembership.SyncJobRowKey == null) { throw new ArgumentNullException("SyncJobRowKey must be set."); }
foreach (var message in groupMembership.Split().Select(x => new Message
{
Body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(x)),
SessionId = groupMembership.RunId.ToString(),
ContentType = "application/json",
Label = sentFrom
}))
{
await _queueClient.SendAsync(message);
}
}
}
}
This could be due to deadlock in the thread pool, please check if you are calling an async method from a sync method.

How to get all the session id of a queue in azure service bus .Net Core

i'm making a web application which is connected to Azure by using .Net Core 2.1.1. I encountered some problem related with service bus queue when i'm trying to get the sessionid of the related queue.
I found some code, but it isn't supported by the .Net Core. Here below is the code:
var queueClient = QueueClient.CreateFromConnectionString(AppSettings.ServiceBusConnection, queueName);
var sessions = await queueClient.GetMessageSessionsAsync();
return sessions;
I also already tried this function,
var connString = Configuration.GetConnectionString("servicebus");
sessionClient = new SessionClient(connString, queue,ReceiveMode.PeekLock);
List<IMessageSession> sessions=new List<IMessageSession>();
while (true)
{
var session = await sessionClient.AcceptMessageSessionAsync();
if (session == null)
break;
sessions.Add(session);
}
return sessions;
}
But it keep giving me Timeout Exception. Can anyone help me ?
This is something which i tried and it worked for me, Please check the screenshot below
Here is the code i have tried
using System;
namespace Core.SBConsole
{
using Microsoft.Azure.ServiceBus;
using Microsoft.Azure.ServiceBus.Core;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
class Program
{
// Connection String for the namespace can be obtained from the Azure portal under the
// 'Shared Access policies' section.
const string ServiceBusConnectionString = "{Connection String}";
const string QueueName = "mvq";
static IMessageSender messageSender;
static ISessionClient sessionClient;
const string SessionPrefix = "session-prefix";
static void Main(string[] args)
{
MainAsync().GetAwaiter().GetResult();
}
static async Task MainAsync()
{
const int numberOfSessions = 5;
const int numberOfMessagesPerSession = 3;
messageSender = new MessageSender(ServiceBusConnectionString, QueueName);
sessionClient = new SessionClient(ServiceBusConnectionString, QueueName);
// Send messages with sessionId set
await SendSessionMessagesAsync(numberOfSessions, numberOfMessagesPerSession);
// Receive all Session based messages using SessionClient
await ReceiveSessionMessagesAsync(numberOfSessions, numberOfMessagesPerSession);
Console.WriteLine("=========================================================");
Console.WriteLine("Completed Receiving all messages... Press any key to exit");
Console.WriteLine("=========================================================");
Console.ReadKey();
await messageSender.CloseAsync();
await sessionClient.CloseAsync();
}
static async Task ReceiveSessionMessagesAsync(int numberOfSessions, int messagesPerSession)
{
Console.WriteLine("===================================================================");
Console.WriteLine("Accepting sessions in the reverse order of sends for demo purposes");
Console.WriteLine("===================================================================");
for (int i = 0; i < numberOfSessions; i++)
{
int messagesReceivedPerSession = 0;
// AcceptMessageSessionAsync(i.ToString()) as below with session id as parameter will try to get a session with that sessionId.
// AcceptMessageSessionAsync() without any messages will try to get any available session with messages associated with that session.
IMessageSession session = await sessionClient.AcceptMessageSessionAsync();// (SessionPrefix + i.ToString());
if (session != null)
{
// Messages within a session will always arrive in order.
Console.WriteLine("=====================================");
Console.WriteLine($"Received Session: {session.SessionId}");
while (messagesReceivedPerSession++ < messagesPerSession)
{
Message message = await session.ReceiveAsync();
Console.WriteLine($"Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
// Complete the message so that it is not received again.
// This can be done only if the queueClient is created in ReceiveMode.PeekLock mode (which is default).
await session.CompleteAsync(message.SystemProperties.LockToken);
}
Console.WriteLine($"Received all messages for Session: {session.SessionId}");
Console.WriteLine("=====================================");
// Close the Session after receiving all messages from the session
await session.CloseAsync();
}
}
}
static async Task SendSessionMessagesAsync(int numberOfSessions, int messagesPerSession)
{
if (numberOfSessions == 0 || messagesPerSession == 0)
{
await Task.FromResult(false);
}
for (int i = numberOfSessions - 1; i >= 0; i--)
{
var messagesToSend = new List<Message>();
string sessionId = SessionPrefix + i;
for (int j = 0; j < messagesPerSession; j++)
{
// Create a new message to send to the queue
string messageBody = "test" + j;
var message = new Message(Encoding.UTF8.GetBytes(messageBody));
// Assign a SessionId for the message
message.SessionId = sessionId;
messagesToSend.Add(message);
// Write the sessionId, body of the message to the console
Console.WriteLine($"Sending SessionId: {message.SessionId}, message: {messageBody}");
}
// Send a batch of messages corresponding to this sessionId to the queue
await messageSender.SendAsync(messagesToSend);
}
Console.WriteLine("=====================================");
Console.WriteLine($"Sent {messagesPerSession} messages each for {numberOfSessions} sessions.");
Console.WriteLine("=====================================");
}
}
}
Things to consider before creating queue
1) Make sure service bus is not in the free or basic tier, if yes then scale it to Standadrd
2) Make sure to enable session while creating queue.
I am using Microsoft.Azure.ServiceBus nuget pakcage 3.4 which is latest now.If you are using some other package try to upgrade/downgrade it.
Hope it helps.

Access ServiceStack session from ConnectionFilter

I am using SQL Server and database triggers to keep a data-level audit of all changes to the system. This audit includes the userID / name of whomever initiated a change. Ideally I'd like to do something like this in my AppHost.Configure method:
SqlServerDialect.Provider.UseUnicode = true;
var dbFactory = new OrmLiteConnectionFactory(ConnectionString, SqlServerDialect.Provider)
{
ConnectionFilter = (db =>
{
IAuthSession session = this.Request.GetSession();
if (session != null && !session.UserName.IsNullOrEmpty())
{
System.Data.IDbCommand cmd = db.CreateCommand();
cmd.CommandText = "declare #ci varbinary(128); select #ci = CAST(#Username as varbinary(128)); set context_info #ci";
System.Data.IDbDataParameter param = cmd.CreateParameter();
param.ParameterName = "Username";
param.DbType = System.Data.DbType.String;
//param.Value = session.UserName;
param.Value = session.UserAuthId;
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
}
return new ProfiledDbConnection(db, Profiler.Current);
}),
AutoDisposeConnection = true
};
container.Register<IDbConnectionFactory>(dbFactory);
Of course, this doesn't work because this.Request doesn't exist. Is there any way to access the current session from the ConnectionFilter or ExecFilter on an OrmLite connection?
The other approach I had started, doing an override of the Db property of Service, doesn't work any more because I've abstracted some activities into their own interfaced implementations to allow for mocks during testing. Each of these is passed a function that is expected to return the a DB connection. Example:
// Transaction processor
container.Register<ITransactionProcessor>(new MockTransactionProcessor(() => dbFactory.OpenDbConnection()));
So, how can I ensure that any DML executed has the (admittedly database-specific) context information needed for my database audit triggers?
The earlier multi tenant ServiceStack example shows how you can use the Request Context to store per-request items, e.g. you can populate the Request Context from a Global Request filter:
GlobalRequestFilters.Add((req, res, dto) =>
{
var session = req.GetSession();
if (session != null)
RequestContext.Instance.Items.Add(
"UserName", session.UserName);
});
And access it within your Connection Filter:
ConnectionFilter = (db =>
{
var userName = RequestContext.Instance.Items["UserName"] as string;
if (!userName.IsNullOrEmpty()) {
//...
}
}),
Another approach is to use a factory pattern, similar to how ServiceStack creates OrmLite db connections in the first place. Since all user-associated calls are made via the ServiceRunner, I piggy-back off of the session that's managed by ServiceStack.
public class TransactionProcessorFactory : ITransactionProcessorFactory
{
public ITransactionProcessor CreateTransactionProcessor(IDbConnection Db)
{
return new TransactionProcessor(Db);
}
}
public abstract MyBaseService : Service
{
private IDbConnection db;
public override System.Data.IDbConnection Db
{
get
{
if (this.db != null) return db;
this.db = this.TryResolve<IDbConnectionFactory>().OpenDbConnection();
IAuthSession session = this.Request.GetSession();
if (session != null && !session.UserName.IsNullOrEmpty())
{
IDbCommand cmd = db.CreateCommand();
cmd.CommandText = "declare #ci varbinary(128); select #ci = CAST(#Username as varbinary(128)); set context_info #ci";
IDbDataParameter param = cmd.CreateParameter();
param.ParameterName = "Username";
param.DbType = DbType.String;
//param.Value = session.UserName;
param.Value = session.UserAuthId;
cmd.Parameters.Add(param);
cmd.ExecuteNonQuery();
}
return db;
}
}
private ITransactionProcessor tp = null;
public virtual ITransactionProcessor TransactionProcessor
{
get
{
if (this.tp != null) return tp;
var factory = this.TryResolve<ITransactionProcessorFactory>();
this.tp = factory.CreateTransactionProcessor(this.Db);
return tp;
}
}
}
For the sake of potential future ServiceStack users, another approach would be to use OrmLite's Global Insert/Update filters combined with Mythz's approach above to inject the necessary SQL only when DML actions are made. It isn't 100%, since there may be stored procs or manual SQL, but that's potentially handled via an IDbConnection extension method to manually set desired auditing information.

How to get last login details/time for all users?

I am trying to remove the user accounts which are inactive from last 30 days.
I tried fetching User Information List. Checked all of it's properties and fields but coudn't find anything related to last login time.
You can do something like this
public DateTime Get(string attr, string UserName)
{
DomainConfiguration domainConfig = new DomainConfiguration();
using (new SPMonitoredScope("AD Properties"))
{
using (DirectoryEntry domain = new DirectoryEntry("LDAP://" + domainConfig.DomainName, domainConfig.UserName, domainConfig.Password))
{
//DirectorySearcher searcher = new DirectorySearcher(domain, "(|(objectClass=organizationalUnit)(objectClass=container)(objectClass=builtinDomain)(objectClass=domainDNS))");
DirectorySearcher searcher = new DirectorySearcher(domain);
searcher.PageSize = 1000;
searcher.Filter = "(SAMAccountName='" + UserName + "')";
//searcher.Filter = "(|(objectCategory=group)(objectCategory=person))";
searcher.Filter = "(&(objectClass=user) (cn=" + UserName + "))";
var user = searcher.FindOne();
DateTime LastLogon = DateTime.FromFileTime((Int64)user.Properties["lastLogon"].Value);
return LastLogon;
}
}
}
Hope this Helps you.
I do not know why it does gives me the some older dates than i expected.
but at least it will compile and run.
using System.DirectoryServices.AccountManagement;
private static DateTime? GetUserIdFromDisplayName(string displayName)
{
// set up domain context
using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
{
// find user by display name
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, displayName);
if (user != null)
{
return user.LastLogon;
}
else
{
return null;
}
}
}

Shared Variable in C# .Net MVC Thread

I am uploading videos to server in .Net MVC application. Since it is takes some time I am doing in a background thread. On the other hand I am tracking the upload progress and display it to the user.
Here is my code
public class MyController : Controller
{
long chunkSize = 256 * 1024;
private static string _progress = ""; //if I make nonstatic it fails
//..........
//Some codes here
//..........
//Upload file Request
public ActionResult VideoUploader()
{
var client = (VimeoClient)Session["client"];
Ticket t = client.vimeo_videos_upload_getTicket();
string path = #"E:\d2.MOV"; //Hardcoded value for testing purposes
new Thread(() => Transfer(client, t, path)).Start(); //Push file to server in background
return PartialView("_progress", "Preparing to upload...");
}
//Worker Thread
private void Transfer(VimeoClient client, Ticket t, string path)
{
FileInfo UploadFile = new FileInfo(path);
int chunks = (int)Math.Floor(Convert.ToDouble(UploadFile.Length / chunkSize));
for (int i = 0; i <= chunks; i++)
{
string output = client.PostVideo(t, i, path,(int) chunkSize);
var v = client.vimeo_videos_upload_verifyChunks(t);
double percentage = (Convert.ToDouble(i + 1) / (chunks + 1)) * 100;
_progress = percentage.ToString() + "%"; // value sharing between two actions
}
string name = client.vimeo_videos_upload_complete(path, t);
client.vimeo_videos_embed_setPreset(client.Token, "200772", name);
}
//This method is calling from front end using jQuery to display progress
public ActionResult Progress()
{
//returning updated shared "_progress" varibal
return Json(_progress, JsonRequestBehavior.AllowGet);
}
}
My problem is when I made "_progress" nonstatic variable(private static _progress) it is not working. Value is always empty.
What I trying to do is share _progress variable between main thread and new thread. But it is failing when it nonstatic.
Please help me to correct. If you have a better option please share
Thanks in advance
You should be returning some sort of "operation ID" to the client as part of the original response. The Progress method should then take this operation ID as a parameter. The upload service should then store its progress against that operation ID (e.g. in a database, to allow you to scale horizontally).
Basically, you should imagine the situation where there are multiple transfers involved - you need some way of getting the progress for the right transfer.
Instance of MyController is created per request.
After you spin the worker thread you return the page to the client and that instance is gone.
You can pass this(i.e. the controller instance) to the Transfer method like this
new Thread(() => Transfer(this, client, t, path)).Start();
and then access the _progress variable in the Transfer method like this
private void Transfer(MyController controller,
VimeoClient client, Ticket t, string path)
{
controller._progress
the page is already returned, so you'll just be able to access the instance _progress field, but then how do you update the client?
you can either
return in the view an animated gif and make a periodical request to the server with javascript OR
use a library like SignalR to 'push' the progress update to the client

Resources