i am using spring security for authentication and if i have 2 servers (server1, server2) using the same file war.
the User A make login in server 1, saving data on persistent_logins table. If the user A makes refresh on server 2, is automatically logged. This is correct but if the u*ser A (server1)* makes logout, the data of table persistent_logins is removed and the user A(server 2) when makes refresh, still connect.
What i can do to user A(server 2) change to logout mode?
thanks
If you know how to catch the moment when you need to make user_A log out, you may consider using filters and clearing the current session.
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// skip non-http requests
if (!(request instanceof HttpServletRequest)) {
chain.doFilter(request, response);
return;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
httpRequest.getSession().invalidate();
...
If you need to inject some beans using spring, you may have a look at DelegatingFilterProxy
The easiest solution update data on both server when user logout
Related
I want to log requests made by users on my webservice. User logs in then user can do requests against servers api. I want to log which user made which request, what was the input and output so on.
Lets say user edits something, by submitting new object to server which will be updated, i want to know who did that, what was it before.
This is what i use at the moment, but it is not very effective.
logging.level.org.thymeleaf=DEBUG
logging.level.org.springframework.boot=TRACE
One idea i have is to add method(...., String Username) so i could log everything. Is this a solid idea, or there is better way to do this?
You can either go with the normal access logging (Tomcat) by enabling this property:
server.tomcat.access-log-enabled=true
This allows you to log anything specified in the AccessLogValve docs.
You can also write your own filter, for example:
#Component
#Ordered(Ordered.LOWEST_PRECEDENCE)
public class LogFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// Log the info you need
// ...
filterChain.doFilter(request, response);
}
}
If you make sure that this filter is executed after the Spring Security filter chain, you have access to the users principal. You also have the HttpServletRequest and HttpServletResponse objects, which will allow you to log both the request body and the response body, though I think that would be a very expensive operation.
The path can be logged with request.getServletPath()
The username can be logged in various ways, such as SecurityContextHolder.getContext().getAuthentication().getName(). Just make sure that your security filter has been executed already by changing the order (for more info look at this question)
The request body can be logged by getting the request.getReader() and log it (for more info look at this question)
The response body can be retrieves as well by creating your own Writer wrapper and overriding the HttpServletResponse so that it returns your writer rather than the default one (for more info look at this question)
While working on a Java Servlet Filter to integrate with an internal SSO I struggled to find the correct way to create a persistent login using programmatic security functions. Specifically, after reading many tutorials such as this I was calling request.login(username,password) and a user Principal was created that returned correct values for methods request.isUserInRole(role) etc. for the current request.
I expected this to be persistent for the user, but subsequent requests would return null for request.getUserPrincipal() so my authentication code was entered on every request. What I found here after much searching was that calling request.getSession(true) before calling request.login(username,password) causes the Principal to be persistent for the user session.
Is it required to explicitly create a session before logging the user in to persist the Principal for the session? This behaviour seems odd to me so I am wondering if I am doing something wrong. I appreciate any insight from developers more knowledgeable on the matter than myself. Using JDK 7 and Tomcat 8. Realm is an extension of RealmBase that overrides authenticate(username,password), getName(), getPassword(username) and getPrincipal(username).
public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
if(request.getUserPrincipal() == null) {
try {
String userName = request.getParameter(userNameField);
String password = request.getParameter(passwordField);
request.getSession(true); // <-- block always entered without this
request.login(username,password);
}
catch(ServletException e) {
// Handle failed login...
return;
}
}
fc.doFilter(req,res);
}
The answer is in the Tomcat source for AuthenticatorBase.java where the login(username,password) chaining calls the configured Realm's authenticate(username,password) method and then calls register(...) passing the returned Principal and stores it in a session if one exists.
I'm new to the use of jsp's, servlets, beans etc ... .
Maybe a strange question, but what is the safest way to make a selection menu in a jsp, to make sure you can't access it directly.
At this moment I have a login system and depending of the "kind" of user I retrieve from the db I send them to a specific jsp depending on the "permissions" they have. On this page they will get a selection of the possibilities they can do.
but if I use something like:
next option
it would be easy to just access these next pages from the outside (not much use for the login system then).
I can use a bean I retrieve from the previous page that I check if it's null (this would be so if you get directly to this page) or something like that.
Any suggestions would be welcome. thx
You can use a Servlet Filter to validate if the user has logged in the system and to verify if the user has the rights to access to this page. An example would be as stated in StackOverflow Servlet-Filters wiki. Posting the relevant code:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
//session.getAttribute("user") contains the user info in session
if (session == null || session.getAttribute("user") == null) {
// No logged-in user found, so redirect to login page.
response.sendRedirect(request.getContextPath() + "/login");
} else {
// Logged-in user found, so just continue request.
chain.doFilter(req, res);
}
}
Our application is using Wicket. We're using Wicket's own forms to handle authentication, the main benefits being that the look of the site is kept consistent.
We thought we couldn't do container authentication because our application allows the user to switch authentication mechanisms mid-stream, and Jetty itself was creating quite a bit of friction anyway, just getting simple authentication to work at the container level.
So we ended up implementing authentication via a filter (there are a number of good examples out there.)
Now I have discovered that by doing this, Wicket authentication is slightly broken. What happened was:
Anonymous user would visit the site.
Security filter determines that the user isn't authenticated and redirects to sign-in.
Wicket renders the sign-in page.
User signs in.
Wicket processes the post to the sign-in form and redirects user back.
Security filter determines that the user isn't authenticated and redirects...
I looked inside my subclass of AuthenticatedWebSession, hoping to find some way I could get a hold of the HttpSession and set a session attribute which could then be checked from the filter. However I couldn't for the life of me find a way to do it.
What I resorted to doing was making yet another filter, coded like this:
public class StealWicketUserFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// Nothing to initialise.
}
#Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException
{
filterChain.doFilter(servletRequest, servletResponse);
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
if ("POST".equals(httpServletRequest.getMethod()) &&
"/sign_in".equals(httpServletRequest.getRequestURI())) {
HttpSession session = httpServletRequest.getSession();
ServerUser currentUser = (ServerUser)
session.getAttribute("wicket:webUIServlet:currentUser");
if (currentUser != null) {
session.setAttribute(CombinedSecurityFilter.CURRENT_USER_ATTRIBUTE,
currentUser);
}
}
else if ("/sign_out".equals(httpServletRequest.getRequestURI())) {
HttpSession session = httpServletRequest.getSession();
session.removeAttribute(CombinedSecurityFilter.CURRENT_USER_ATTRIBUTE);
}
}
#Override
public void destroy() {
// Nothing to destroy.
}
}
This of course works (and will continue to work until Wicket change the prefix they store session attributes under.)
I guess what I want to know is whether this is a bad idea and whether there is a "proper Wicket way" to do this sort of thing.
As for the reason we don't use Wicket's authentication alone - the reason is that we wanted to support SPNEGO authentication and potentially other external authentication types.
You can get hold of your HttpSession,albeit through Request and not Session.
What you need is:
WebRequest req = (WebRequest)RequestCycle.get().getRequest();
HttpSession session = req.getHttpServletRequest().getSession();
However I'm pretty sure Wicket authentication isn't broken in such an obvious manner so I'd probably try to find out what is causing this glitch instead.
I need to be able to maintain a session by having the JSESSIONID specified as a parameter of the query string of the url rather than part of the URL itself.
I other words I need to maintain a session like this
http://myserver.com?jsessionid=A463B23BC4F2342FA
rather than
http://myserver.com;jsessionid=A463B23BC4F2342FA
For a servlet container I'm using both tomcat 6.0 and weblogic 10.3
Reason:
I'm creating a Google Earth network link which requires me to keep a session for the requests a client makes. Google Earth doesn't support cookies and it appears there is no way to change the url that it uses to make requests. I can only tell it to append a query string parameter on subsequent requests by adding the following to the kml in my server responses
<NetworkLinkControl>
<cookie>JSESSIONID=A463B23BC4F2342FA</cookie>
</NetworkLinkControl>
Not possible. I'd create on your side a filter which redirects the request to the proper URL whenever an URL arrives with the JSESSIONID in the query string.
Basic kickoff example:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if ("GET".equals(request.getMethod()) && request.getParameter("JSESSIONID") != null) {
response.sendRedirect(request.getRequestURL().append(";JSESSIONID=")
.append(request.getParameter("JSESSIONID")).toString());
} else {
chain.doFilter(request, response);
}
}
Map this on an URL pattern which covers requests which could potentially originate by that site. Or if there is none, just on /*.
We have created custom Tomcat Valve for this purpose. It's pretty straightforward, but Tomcat-specific.