Laravel has an account lock function.
But it is based on IP address.
It can also be disguised.
Therefore, I want to lock the account itself regardless of the difference in IP address
How can I do?
I made a package for this :)
You can block users, emails, ip addresses, domain names, cities, states, countries, continents, and regions from using your application, logging in, or registering.
https://github.com/jeremykenedy/laravel-blocker
Throttling is not locking so even if you changed it to not be bound to the IP the account will be able to log in again after waiting for some time.
If this is what you want to do then you can override the throttleKey function to use a key not based on IP. If you want to completely ban someone then you can also probably override the decayMinutes to a value of say 100 years.
For example in your normal auth controller:
class class LoginController extends Controller {
use AuthenticatesUsers;
// ...
public $decayMinutes = 52560000; // 100 years
protected function throttleKey(Request $request)
{
return Str::lower($request->input($this->username())); // No IP here now
}
}
Note: Since the rate limiter stores the values in the cache, then clearing the cache will also clear the blocked users. If you want a more permanent solution you can probably add a flag on the user entry in the database indicating that the user is blocked. This is just a quick and dirty solution to get things working for you quickly.
As another note: Not blocking by IP means you're locking someone out if someone else tries to hack into their account. This might be a bit infuriating for your users, which is also something to consider.
Related
In spring boot application only one user should be using the certain page at a time (let's call it home.jsp). Another users should be redirected to different page(let's call it another_home.jsp) if they appear when accessing that same url. User doesn't login and just uses the application as it is. Any policy can be used for home.jsp could be first-come-first-serve or any other.
If more than one users are using application at a time only one user should be using home.html and all rest of the others should be using another_home.jsp.
As no login is needed in the application I believe I need anonymous sessions. Also, session needs to be expired after some time of inactivity. I've searched spring security but couldn't find anything.
I think that you don't even need spring security. Simple http session will work too. As far as I can see you just want to allocate the stream to one user and for that you need first user's session id which you can compare against whenever the requests come again. So store session id and expire after some timeout with some Time object or Date object.
In properties
server.servlet.session.timeout = 600 // 10 minutes
Something like this
private String currSessionId = null;
private Date lastDate = new Date();
private Integer TIMEOUT = 600000; // 10 minutes
public String loadHomePage(Model model) {
if(currSessionId!=null && new Date().getTime()- lastDate.getTime()>TIMEOUT){
currSessionId = null;
}
if(currSessionId==null){
currSessionId = session.getId();
lastDate = new Date();
return "home";
}else{
if(session.getId().equals(currSessionId)){
return "home";
}else{
return "another_home";
}
}
}
This is as simple as it gets when you don't have logged in users to manage and also don't need to remember previous state where user left off. Let me know if it helps.
You need to create a serverside state that is either empty or stores the identifier of the visitor that is currently claiming /home.jsp.
This could be a field on a singleton Bean, or an entity in the database.
It has to expire automatically, or it will prevent new visitors forever to make a claim.
As long as the state is empty, the first visitors identifier will be stored in this state.
And from that moment on, you will redirect all other visitors to another_home.jsp
So the Controllers Code would be something like this
if(visitorHoldsTheClaim()) {
return "home.jsp"
} else if (noClaimActive()) {
createClaimForVisitor();
return "home.jsp"
} else {
return "redirect:/another_home.jsp"
}
Depending on your implementation, these methods will do different things.
I'd usually recommend against serverside session state (more about this in Roy Fieldings Dissertation),
but for your use case, you need a way to identify a visitor over many requests.
A session would certainly be a very simple way to achieve this.
You can at least minimize session usage by only creating one session at a time - the one for the visitor that holds the claim.
In this case you'd never have more than one open session, and the visitor that owns the session is the visitor that holds the claim.
So in this case, the implementation would be be something like this:
if(currentUserHasASession()) { // checks if the current user has a session, but !!!does not create a new session if it does not exist!!! careful, HttpServletRequest.getSession(true) would create it!
return "home.jsp"
} else if (serverHasNoSessions()) { // https://stackoverflow.com/questions/49539076/how-can-i-get-a-list-of-all-sessions-in-spring
createSessionForUser(); // HttpServletRequest.getSession(true)
return "home.jsp"
} else {
return "redirect:/another_home.jsp"
}
Keep in mind that this only works if you do not create Sessions in another place.
So you have to configure Spring Boot/Spring Security to not create Sessions. How to make spring boot never issue session cookie?
Also keep concurrency in mind. For example, if you had only one server instance, you could put this code into a synchronized method to avoid two visitors creating a claim at the same time.
So... first of all, this sounds like a bad idea. I would be curious why you would need such an unusual behavior. There might be more sensible approaches for it.
Like Gregor said, the redirect code part is rather straightforward:
if(pageLock.getUser() == null) {
pageLock.setUser(user);
}
if(user.equals(pageLock.getUser())) {
return "home.jsp"
} else {
return "redirect:/another_home.jsp"
}
What is actually more tricky is the part when "expiring" the lock. It's likely the user will simply close the browser and not click on "logout" (or whatever), leaving the lock forever. On the other extreme, the user might be gone for a lunch break but its browser still has the page open for hours.
So that's the first thing you wanna add: some keep-alive mechanism on the page, regularly prolonging the lock, and some expiration checker, releasing the lock if nothing was received for a while.
...but like I said in the beginning, the whole thing sounds fishy.
I'm using Sentinel in Laravel for user management. I logged in 2 users and I try to get a list of all logged in users but this only returns the very last user to log in.
The code below is one of my attempts. I know im doing it wrong pls help.
public function getLoggedInUsers(Request $request,User $user)
{
$loggedinUser ="";
foreach($user as $loggedinUser){
return Sentinel::getUser($loggedinUser);
}
}
It returns only the last logged in User instead of a list of all logged in users
The return key will exit the function getLoggedInUsers() the first time it is hit. This means your foreach loop is only executing one time and immediately returning the first user. Additionally, your $user variable is a single user, meaning there is nothing to loop over, it will only execute one time regardless.
I could not find in the documentation if Sentinel has a function for getting all active users.
I'm not sure if Sentinel supports it, but if the User sessions can be saved to the database instead of the filesystem, then you should be able to check to the sessions table for active users. In basic Laravel authentication, you can change where the user sessions are stored. Sentinel might have something similar or might use config/session.php as well. (https://laravel.com/docs/5.8/session)
I have a public Stored process (STP) in which I would like to be able to identify which page is calling it, via ajax.
The STP is momentarily set to run with a guest account and is thus public.
I thought to do it by inserting a secret Key in the STP variables.
But that key can be changed by users in the url.
Is there a method to identify that without leaving the possibility to users to change it?
Maybe there is a reserved STP variable that tells the origin of the request (like the server name or ip or something identifiable)?
But I could not find any among those:
_debug
_grafloc
_htcook
_htua
_program
_reqmeth
_rmtaddr
_rmthost
_srvname
_srvport
_url
_userlocale
_username
_version
http://support.sas.com/rnd/itech/doc9/dev_guide/stprocess/reserved.html
Changing my answer as I was previously incorrect. You CAN get this information (via _htrefer) but it requires a configuration change to your SAS server. As per documentation:
_HTREFER: Specifies the address of the referring page. This variable is not set by default but can be enabled in the params.config
file.
It's worth noting that no method can ever be 100% reliable as end users can always manipulate their requests.
We are starting to use Epicor 10 and we are wanting to leverage the DLLs/Services to talk to Epicor. That way we can add/update info from a custom app. So far things are going fine but we ran into an issue when we wanted to, lets say, add a job for a specific plant. It seems to always want to save to the plant the user last logged into via the client app.
So for example -- Lets say the user's last plant was plant "A". I want my custom app to log into Epicor (creating a session) and create a job for plant "B". I can add the job fine, but it will put it under plant "A" and not "B", even though I logged into plant "B" when I created the session.
We are calling SetPlant and passing in the right plant we want, but Epicor seems to always override what plant to save it as. Has anyone else run into this case? We are also having this issue with the Company. SetCompany doesnt seem to work at all.
More info: - We are using the net.tcp:///ERP/ICE/Lib/SessionMod.svc service. - We can login fine with Login() and get a SessionId back - Even calling GetValues() on the Session object says we are logged into plant "B" even though Epicor will still use plant "A".
The only work around we can come up with, which we do not want to do, is to have an app user by company and by plant so we can guarantee which company and plant the data gets saved to. This will work but it isnt ideal.
Anyone have any suggestions on how to get the system to take the new Company or Plant?
As user463132 points out, you can wrap your service connection with the temporary session context:
using (CallContext.Current.TemporarySessionCreator.SetCompanyID("YourCompanyHere").SetPlantID("B").Create())
{
}
Haso Keric Article Reference
I'll also add that if you are using the UI adapters, you can simply grab the session from the oTrans object instance and set the properties here which governs how oTrans interacts with your data.
Ice.Core.Session s1 = (Ice.Core.Session)this.oTrans.Session;
s1.CompanyID = "YourCompanyHere";
s1.PlantID = "B";
The plantID can be updated in the session using the SetPlant() method. It must be called after the SetCompany():
sessionModImpl = NetTcp_Helper.ClassAttributHelper.CreateBusObj<SessionModImpl>(Guid.Empty, SessionModImpl.UriPath, Settings);
sessionId = sessionModImpl.Login();
sessionModImpl.SessionID = sessionId;
sessionModImpl.SetCompany(epicorCompanyID, out companyName, out plantID, out plantName, out workstationID, out workstationDescription, out employeeID,
out countryGroupCode, out countryCode, out tenantID);
sessionModImpl.SetPlant(newSiteID, out plantName);
The first thing to understand is that a Server Session is not a single
instance but rather a .NET Stack of Session Instances. The
‘CallContext.Current.Session’ variable is just a pointer to the top of
the Stack. In most cases, there is just a single Session instance in
the CallContext stack. But when you need to iterate over Companies to
process something the Session Stack get pushed and popped around.
That’s where ‘TemporarySessions’ comes in.
Read about it at:
https://www.linkedin.com/pulse/snippet-epicor-change-companyplantuser-bpm-haso-keric/
I want to track users that are online at the moment.
The definition of being online is when they are on the index page of the website which
has the chat function.
So far, all I can think of is setting a cookie for the user and, when the cookie is found on the next visit, an ajax call is made to update a table with their username, their status online and the time.
Now my actual question is, how can I reliably turn their status to off when they leave
the website? The only thing I can think of is to set a predetermined amount of time of no user interaction and then set the status to off.
But what I really want is to keep the status on as long as they are on the site, with or without interaction, and only go to off when they leave the site.
Full Solution. Start-to-finish.
If you only want this working on the index.php page, you could send updates to the server asynchronously (AJAX-style) alerting the server that $_SESSION["userid"] is still online.
setInterval("update()", 10000); // Update every 10 seconds
function update() {
$.post("update.php"); // Sends request to update.php
}
Your update.php file would have a bit of code like this:
session_start();
if ($_SESSION["userid"])
updateUserStatus($_SESSION["userid"]);
This all assumes that you store your userid as a session-variable when users login to your website. The updateUserStatus() function is just a simple query, like the following:
UPDATE users
SET lastActiveTime = NOW()
WHERE userid = $userid
So that takes care of your storage. Now to retrieve the list of users who are "online." For this, you'll want another jQuery-call, and another setInterval() call:
setInterval("getList()", 10000) // Get users-online every 10 seconds
function getList() {
$.post("getList.php", function(list) {
$("listBox").html(list);
});
}
This function requests a bit of HTML form the server every 10 seconds. The getList.php page would look like this:
session_start();
if (!$_SESSION["userid"])
die; // Don't give the list to anybody not logged in
$users = getOnlineUsers(); /* Gets all users with lastActiveTime within the
last 1 minute */
$output = "<ul>";
foreach ($users as $user) {
$output .= "<li>".$user["userName"]."</li>";
}
$output .= "</ul>";
print $output;
That would output the following HTML:
<ul>
<li>Jonathan Sampson</li>
<li>Paolo Bergantino</li>
<li>John Skeet</li>
</ul>
That list is included in your jQuery variable named "list." Look back up into our last jQuery block and you'll see it there.
jQuery will take this list, and place it within a div having the classname of "listBox."
<div class="listBox"></div>
Hope this gets you going.
In the general case, there's no way to know when a user leaves your page.
But you can do things behind the scenes such that they load something from your server frequently while they're on the page, eg. by loading an <iframe> with some content that reloads every minute:
<meta http-equiv="refresh" content="60">
That will cause some small extra server load, but it will do what you want (if not to the second).
Well, how does the chat function work? Is it an ajax-based chat system?
Ajax-based chat systems work by the clients consistently hitting the chat server to see if there are any new messages in queue. If this is the case, you can update the user's online status either in a cookie or a PHP Session (assuming you are using PHP, of course). Then you can set the online timeout to be something slightly longer than the update frequency.
That is, if your chat system typically requests new messages from the server every 5 seconds, then you can assume that any user who hasn't sent a request for 10-15 seconds is no longer on the chat page.
If you are not using an ajax-based chat system (maybe Java or something), then you can still accomplish the same thing by adding an ajax request that goes out to the server periodically to establish whether or not the user is online.
I would not suggest storing this online status information in a database. Querying the database every couple of seconds to see who is online and who isn't is very resource intensive, especially if this is a large site. You should cache this information and operate on the cache (very fast) vs. the database (very slow by comparison).
The question is tagged as "jquery" - what about a javascript solution? Instead of meta/refresh you could use window.setInterval(), perform an ajax-request and provide something "useful" like e.g. an updated "who's online" list (if you consider that useful ;-))
I have not tried this, so take it with a grain of salt: Set an event handler for window.onunload that notifies the server when the user leaves the page. Some problems with this are 1.) the event won't fire if the browser or computer crashes, and 2.) if the user has two instances of the index page open and closes one, they will appear to logout unless you implement reference counting. On its own this is not robust, but combined with Jonathan's polling method, should allow you to have pretty good response time and larger intervals between updates.
The ultimate solution would be implementing something with websockets.