How to add Logout from all other session - javascript

My scenario is there are two different users login with same user id and password.mean time one of the person change the password by giving the current password. And changed the password at same time the another user gives current password what he logged in was incorrect. So i wants to add logout from all other devices in my web application.how can i do that

There is of course more than one approach, my first idea would be to hook the sessions to the ServletContext. Something like
// this can be in some util class, let's call it SessionUtil
static final String SESSION_REGISTER = "session.register";
public static synchronized void registerSession(ServletRequest req, HttpSession ses, String userName) {
ServletContext ctx = req.getServletContext();
Map<String, List<HttpSession>> register = (Map<String, List<HttpSession>>) ctx.getAttribute(SESSION_REGISTER);
if (register == null) {
register = new HashMap<>();
ctx.setAttribute(SESSION_REGISTER, register);
}
List<HttpSession> sessions = register.computeIfAbsent(userName, k -> new ArrayList<>());
sessions.add(ses);
}
Then, in your code, you need to register the user's session after login:
HttpSession ss = request.getSession();
if (isUser(name,password)) {
ss.setAttribute("user",name)
SessionUtil.registerSession(request, ss, name);
}
Finally, you need a method (again in SessionUtil class) to invalidate all the user's sessions (except the current one):
public static synchronized void invalidateSessions(ServletRequest req, HttpSession current, String userName) {
ServletContext ctx = req.getServletContext();
Map<String, List<HttpSession>> register = (Map<String, List<HttpSession>>) ctx.getAttribute(SESSION_REGISTER);
if (register != null) {
List<HttpSession> sessions = register.get(userName);
if (sessions != null) {
for (HttpSession ses : sessions) {
if (!ses.equals(current)) {
ses.invalidate();
}
}
}
}
}
Then you can call this method e.g. when the user changes his/her password.
Note #1: Not a very nice code, it misses some sanity checks and synchronized can be smaller chunks of code. It's just to give you an idea.
Note #2: The functionality of the registerSession(...) method can be done using the HttpSessionAttributeListener, but I've never used it yet, so cannot give an example.

Related

How is a map initialised in memory

I just tarted to write solidity and i have some questions that i could not find the answer to.
When you declare a map like this:
struct UserAccount{
string name;
uint id;
}
mapping (address => UserAccount) public accounts;
How will that be initialised? or with what?
For example, accessing
accounts[0x79d66c53ad6f1847288c0d06c01a2b38c38f15bc]
will return an instance of an UserAccount? If yes, that means that the map creates an instance of UserAccount for every possible address? Doesn't that consume very much memory? If not, then how comes you can do this:
accounts[_address].name = _name;
?
And the second question:
I keep reference in my contract of an address that is the owner, the address that created the contract:
address public owner;
constructor() public {
owner = msg.sender;
}
After i call this function:
uint userCount=0;
mapping (address => UserAccount) public accounts;
function createAccount(string _name, uint _id, address _address) onlyOwner() public {
UserAccount user;
user.name = _name;
user.id = _id;
accounts[_address] = user;
userCount += 1;
// accounts[_address].name = _name;
// accounts[_address].id = _id;
// userCount += 1;
emit UserCreated(_address, _id, _name);
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
the owner address changes. The commented lines from createAccount function are the way to do it, i know, but i want to understand why it does not work.
To clarify my problem i will also post a js test.
beforeEach(async () => {
voting = await Voting.new({from: owner});
});
it("Should delete poll, as owner", async () =>{
var name = "Sandu";
console.log("LOCAL OWNER= " + owner);
console.log("OWNER BEFORE CREATE ACCOUNT FROM SOL= " + await voting.owner());
await voting.createAccount(name, 1, firstUser,{from:owner});
console.log("OWNER AFTER CREATE ACCOUNT FROM SOL= " + await voting.owner());
var pollName = "First Poll";
var endDateS="2018-08-11T10:20:30Z";
var endDate=new Date(endDateS)
await voting.createPoll(pollName, 1, endDate.getTime()/1000,{from:firstUser});
try{
await voting.deletePollById(1,{from: owner});
}catch(err){
console.log(err.message);
}
assert.notEqual(pollName, await voting.getPollById(1));
});
The test above prints this:
LOCAL OWNER= 0x79d66c53ad6f1847288c0d06c01a2b38c38f15bc //Owner that o have in my js file local, first address from the ganache accounts.
OWNER BEFORE CREATE ACCOUNT FROM SOL= 0x79d66c53ad6f1847288c0d06c01a2b38c38f15bc //The owner account from my contract before calling the function
OWNER AFTER CREATE ACCOUNT FROM SOL= 0x000000000000000000000000000000000000000a //The owner account from my contract after calling the function
I can't understand why the value from owner changes as i don't touch that in my function.
If anyone can help it would be much appreciated. Again, i know the right way to do it but i am posting this out of the desire to understand what i am doing not to get the job done.
Please do not post multiple questions in a single post as it will result in the question being closed as too broad.
For your first question, all variables have an initial default value. From the Solidity docs:
Mappings can be seen as hash tables which are virtually initialized such that every possible key exists and is mapped to a value whose byte-representation is all zeros: a type’s default value.
No storage is used for zero values.
For your second question, you're overwriting the state variable because you're using a storage variable where you should be using a memory variable. See the answer provided here: what are state variables in solidity?

Wicket AbstractDefaultAjaxBehavior do recursive update the page

I have some ajax Behaviour that should pick some data using JS, and turn it back to Java. Sometimes it works but quite ofen it is just add url parameter and do page refresing/
public abstract class LoggedVKIdBehaviour extends AbstractDefaultAjaxBehavior {
private static final Logger logger = LoggerFactory.getLogger(LoggedVKIdBehaviour.class);
#Override
protected void respond(AjaxRequestTarget target) {
String loggedVkId = RequestCycle.get().getRequest().getRequestParameters().getParameterValue("logged_vkid").toString();
logger.info("ajax has comming with logged VK ID " + loggedVkId);
recived(target, loggedVkId);
}
protected abstract void recived(AjaxRequestTarget target, String loggedVkId);
#Override
public void renderHead(final Component component, IHeaderResponse response) {
super.renderHead(component, response);
Map<String, Object> map = new HashMap<>();
map.put("callbackFunction", getCallbackFunction(CallbackParameter.explicit("logged_vkid")));
//
PackageTextTemplate ptt = new PackageTextTemplate(LoggedVKIdBehaviour.class, "vkid_callback.js");
OnDomReadyHeaderItem onDomReadyHeaderItem = OnDomReadyHeaderItem.forScript(ptt.asString(map));
response.render(onDomReadyHeaderItem);
}
}
js template
var calback = ${callbackFunction};
var logged_vk_id = 11;
function authInfo(response) {
if (response.session) {
logged_vk_id = response.session.mid;
calback(response.session.mid);
console.log("recived callback from VK " + logged_vk_id);
}
}
$(document).ready(function () {
VK.Auth.getLoginStatus(authInfo);
});
it is do recursive redirection like http://localhost:8080/mytool/product/1?logged_vkid=332797331&logged_vkid=332797331&logged_vkid=332797331&logged_vkid=332797331&logged_vkid=332773...
As i understand Ajaj technology - iti asynchronus requests, that shouldn't touch main url at all. So what is the reason for page refreshing?
this is generated Callback function
function (logged_vkid) {
var attrs = {"u":"../wicket/bookmarkable/com.tac.kulik.pages.product.ProductPage?12-1.IBehaviorListener.0-&productID=1"};
var params = [{"name":"logged_vkid","value":logged_vkid}];
attrs.ep = params.concat(attrs.ep || []);
Wicket.Ajax.ajax(attrs);
}
I use wicket 7.2
I did a lot investigations for few days. And found that when i remove
setPageManagerProvider(new NoSerializationPageManagerProvider(this));
Application throw me exepton in polite logs
org.apache.wicket.WicketRuntimeException: A problem occurred while
trying to collect debug information about not serializable object look
like it is could come from aused by: java.io.NotSerializableException:
com.tac.kulik.panel.smaccounts.SMAccountsPanel$1
which means that page tryed to be serialized for SOME REASON but $1 it is mean Anonimous class. I had few class created anonimously to ges some ajax links coming from ListView to be managed on parent panel. So After removing this Anonimous class logic, everything start and run well.
So i am happy, but still don't understand which reason page did serialization after ajax, and what the reason was to refresh whole page.

SignalR join/leave group doesn't work correctly

I have a simple application using SignalR, where I wan't to display different data for different machines, depending on which machine has been chosen by the user
My Hub class looks like this:
readonly ISprayBroadcaster _sprayBroadcaster;
readonly IWorkRecordRepository _workRecordRepository;
public SprayHub(ISprayBroadcaster sprayBroadcaster, IWorkRecordRepository workRecordRepository)
{
_sprayBroadcaster = sprayBroadcaster;
_workRecordRepository = workRecordRepository;
}
public void Broadcast(string name)
{
Process.DataProcess(_workRecordRepository, Clients, name).Wait();
}
public void SwapGroup(string previousGroup, string newGroup)
{
Groups.Remove(Context.ConnectionId, previousGroup);
Groups.Add(Context.ConnectionId, newGroup);
}
public void JoinGroup(string groupName)
{
Groups.Add(Context.ConnectionId, groupName);
}
This is how I initialize the hub on the client side and call Broadcast method on it:
$(function () {
hub = $.connection.sprayHub;
function init() {
hub.server.joinGroup("machine1");
hub.server.broadcast("machine1");
};
// Client-side hub method that the server will call
hub.client.updateData = function (shifts) {
ViewModel.Measurements(recreateArray(shifts));
}
$.connection.hub.start().done(init);
});
Broadcast method goes to the DataProcess method which populates data to the clients from the assigned group:
public static async Task DataProcess(IWorkRecordRepository workRecordRepository, IHubConnectionContext hubClients, string machine)
{
var shiftRecords = await workRecordRepository.Records(machine, DateTime.Now).ToList();
var result = SLGT.Sentinel.Core.Calculations.Shifts(shiftRecords);
hubClients.Group(machine).updateData(result);
}
At the same time I setup a broadcaster which runs in the loop and feeds clients with appropriate data. This is a broadcast method from the broadcaster which calls the same DataProcess method to populate data for each machine found in the system:
void Broadcast(object state)
{
lock (_updateLock)
{
if (_updating)
return;
_updating = true;
var machines = _workRecordRepository.Machines();
machines.Subscribe(async machine =>
{
await Process.DataProcess(_workRecordRepository, Clients, machine);
});
_updating = false;
}
}
Finally when user clicks a button for different machine on the client side I swap the groups for the appropriate data to be displayed for this client:
$(".machineButton").click(function () {
var name = $(this).attr("id");
hub.server.swapGroup(previousGroup, name);
previousGroup = name;
}
Now, when I run this application in my test environment, everything works fine. When I run it on the server, swap between the groups doesn't work correctly, and the client is constantly fed with the same set of data. Why might it be happening? As I said local version works fine so I do not know how to debug it?
The group management methods (add and remove) are async. If you don't await the returned task then send to the group immediately after you have a race condition such that the client you just added might not receive the message. Also, you should never call .Wait() from in a hub method. Make the hub method async and await it instead.
readonly ISprayBroadcaster _sprayBroadcaster;
readonly IWorkRecordRepository _workRecordRepository;
public SprayHub(ISprayBroadcaster sprayBroadcaster, IWorkRecordRepository workRecordRepository)
{
_sprayBroadcaster = sprayBroadcaster;
_workRecordRepository = workRecordRepository;
}
public async Task Broadcast(string name)
{
await Process.DataProcess(_workRecordRepository, Clients, name);
}
public async Task SwapGroup(string previousGroup, string newGroup)
{
await Groups.Remove(Context.ConnectionId, previousGroup);
await Groups.Add(Context.ConnectionId, newGroup);
}
public async Task JoinGroup(string groupName)
{
await Groups.Add(Context.ConnectionId, groupName);
}
Also, is your production environment a single web server or is it a load-balanced farm? If it's a farm you'll need to configure SignalR scale-out.

Firebase - Count online users

I tried using presence to make it display the total connected users in an element. I can't really figure out how to make it work.
I also tried doing the following:
var dataUlist = new Firebase('https://<url>.firebaseio.com/.info/connected');
dataUlist.on('value', function(snap) {
console.log(snap);
});
To tried to see if I could find anything useful in there, but I couldn't figure out how the data works.
Is there any way to accomplice what I am after? Fetch the total number of connected users and then echo it out in the console or to an element?
.info/connected will only return information about whether the current client is connected or not. In order to maintain a presence count, you'll need to create a counter by storing presence information for each user and utilizing setOnDisconnect(). For example:
var listRef = new Firebase("https://<url>.firebaseio.com/presence/");
var userRef = listRef.push();
// Add ourselves to presence list when online.
var presenceRef = new Firebase("https://<url>.firebaseio.com/.info/connected");
presenceRef.on("value", function(snap) {
if (snap.val()) {
// Remove ourselves when we disconnect.
userRef.onDisconnect().remove();
userRef.set(true);
}
});
// Number of online users is the number of objects in the presence list.
listRef.on("value", function(snap) {
console.log("# of online users = " + snap.numChildren());
});
Here is the the code from Anant formatted for Android
public void getDbCount() {
Firebase listRef = new Firebase("https://<your-firebase-database>.firebaseio.com/presence/");
final Firebase userRef = listRef.push();
// Add ourselves to presence list when online.
Firebase presenceRef = new Firebase("https://<your-firebase-database>.firebaseio.com/.info/connected");
ValueEventListener myPresence = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
// Remove ourselves when we disconnect.
userRef.onDisconnect().removeValue();
userRef.setValue(true);
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("DBCount", "The read failed: " + firebaseError.getMessage());
}
};
presenceRef.addValueEventListener(myPresence);
// Number of online users is the number of objects in the presence list.
ValueEventListener myList = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
// Remove ourselves when we disconnect.
Log.i("DBCount", "# of online users = " + String.valueOf(snapshot.getChildrenCount()));
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("DBCount", "The read failed: " + firebaseError.getMessage());
}
};
listRef.addValueEventListener(myList);
}

Function to add and remove a username

In my chat application project, I am trying to broadcast usernames to all the users whenever a new user is connected to a server. and remove a username whenever the user leaves the server. The below is the code which I have tried by going through tutorials. (please check the file.js file which is not showing the desired output)
Chat.cs (Working) --> Implements "Hub" class of SignalR
public class Chat : Hub
{
/* showing only related content */
static ConcurrentDictionary<string, User> _users = new ConcurrentDictionary<string, User>();
public override Task OnDisconnected()
{
var user = _users[Context.ConnectionId]; //user as ConnectionId
User removedUser; //new class object
_users.TryRemove(Context.ConnectionId, out removedUser);
return Clients.All.leave(user, DateTime.Now.ToString()); //dynamic expression
}
public void Joined()
{
User user = new User(Context.ConnectionId, Clients.Caller.username);
_users.TryAdd(user.ConnectionID, user);
Clients.All.joins(user.ConnectionID, user.Name, DateTime.Now); //dynamic expression
}
}
User.cs (Working)
public class User
{
public User(string ConnID, string Username)
{
Name = Username;
ConnectionID = ConnID;
}
public string Name { get; set; }
public string ConnectionID { get; set; }
}
file.js (not working)
var chatUsername = window.prompt("Enter Username:", ""); //username
var chat = $.connection.chat; //connection
//
chat.client.joins = function (ConnectionId, name, Date) {
ConnectionId = 1; /* given value to just test */
name = chatUsername;
};
chat.client.leave = function (user, date) {
user = ""; //making the string empty so that the disconnected user value will be lost.
};
//Here is the connection which calls the "Joined" function of the server (Chat.cs)
What should I write in file.js functions (joins and leave) so that I will get the desired result as I mentioned above. Before asking here, I have gone through this site which is doing the same but including additional javascript files(knockout.js and json) which I dont want to include.(bcos I am new to jquery).
In order to pass UserNames to the client you can take your dictionary and in your joined server side method you could change the SignalR line to be:
Clients.All.joins(_users.Values); //dynamic expression
Then the client version of joins would be:
chat.client.joins = function (users) {
for(var i = users.length - 1; i >= 0; i--) {
alert("User Name: " + users[i].Name + "\nUser Connection ID: " + users[i].ConnectionID);
}
};
Of course you can handle the user information differently than alerting it, but that's the gist of how to handle the data. Lastly, I'd recommend against passing down the connection ID to everyone because a third party could then easily hijack it.

Categories