Recently I have upgrade my all project API's like Spring, Spring Security, Hibernate, Maven, Java. Before upgrade I was using Spring 3 and Spring Security 2.
Now I am using Spring 4 and Spring Security 4 in my project and I have also used cas authentication for login.
When user logged in my application, based on the initial requested URL I want to set target URL of user. Before upgrade it was working fine.
I was using this SPRING_SECURITY_SAVED_REQUEST_KEY to get initial request URL.
Now I am using -
savedRequest = new HttpSessionRequestCache().getRequest(request, response);
to get initial request but it always return null.
Is there any way to get initial request of user after login?
you can use SavedRequestAwareAuthenticationSuccessHandler
Here is how I used the SavedRequestAwareAuthenticationSuccessHandler.
In my case I had an authorization server at localhost:8081 and the secured UI at localhost:8083/app.
In the Authorization server I created the following class:
#Component
public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
setDefaultTargetUrl("http://localhost:8083/app");
super.onAuthenticationSuccess(request, response, authentication);
}
}
In my case there were 3 scenarios of user logging in:
User navigates to http://localhost:8081/login
User navigates to http://localhost:8083/app
User navigates to any secured url within the app like http://localhost:8083/app/files
The class above covers every one of these scenarios by redirecting the user to the original url or if the user choose to login via http://localhost:8081/login, it redirects them to the default target url which is http://localhost:8083/app.
Related
I have difficulty using Spring Security. I need auto login with parameter in URL.
Example:
I access the URL with username and password parameters
link/collectsys/mainlogin.zul?username=ADMIN&password=12345678.
When it is accessed, I hope it will log in automatically, such as filling in the username and password and clicking the login button.
I'm having trouble finding the action on the login button because I'm using Spring Security. What should I look for in the Spring documentation? I'm using Spring Security version 5.5.3.
You would need to generate a token when you login. This token is then used by the user's client to interact with the REST APIs protected by spring security.
So the login method would need to return to the client an access token that then will be saved in the client's session or cookies to be then reused whenever a call to the backend is made.
One of the common used solutions is the JWT of which you can find a really comprehensive guide here:
https://www.bezkoder.com/spring-boot-jwt-authentication/
If you really cannot change much of the application then you should look into the OncePerRequestFilter that enables you to filter requests of the spring boot application
public class AuthenticationFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws
ServletException, IOException {
String username = request.getParameter("username");
String pw = request.getParameter("password");
User user = database.getUser(username);
if(user.getPw().equals(pw))
logger.info("Successfully authenticated user " + userName);
else throw new SomeException();
filterChain.doFilter(request, response);
}
}
This way which ever request gets to your application passes through this filter once before getting to the controller logic itself.
Please help me on the below item:
Where exactly custom valve used instead of a filter?
In our application, I have created tomcat 9 custom valve and trying to access user principal from the valve. but in the valve, it returns null. but we are able to access from the filter. we have used form-based authentication.
User Principal will be available in Custom valve or is it available on in fliter?
Code snippet is provided below:
public class ContextInitializerValve extends ValveBase {
public ContextInitializerValve() {
System.out.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
}
#Override
public void invoke(Request request, Response response) throws IOException, ServletException {
System.out.println("======================custom valve==============================");
Principal principal = request.getUserPrincipal();
}
}
Thanks in advance
You can think of valves as the equivalent for filters, but server-side, not on the application side. E.g. you'd deploy a valve to the server, and typically can't hot-deploy new versions of it without restarting the server. You could redeploy a filter by redeploying your application that contains the filter.
Both Valves and Filters are order-sensitive: When you use Valves (tomcat uses them for server-side authentication) and you are sure that a user is authenticated, but you don't get the principal, your valve seems to be running before tomcat's authentication valve. You can either make sure to have your valve configured in the correct order, or move the implementation to a filter, because filters always run after all valves have been running.
In principle, they're very similar. Filters are defined by the servlet spec, while Valves (being part of the server implementation) are defined by Tomcat.
I have a Spring Mvc Application using hibernate hosted on ibm bluemix with domain registered in go daddy using tomcat server using the java_buildpack provided by blue mix for tomcat.Currently I have bought a ssl certificate in go daddy registered in blue mix.My application now works both on http and https.But now i have a requirement to enforce only https connection to my application .I implemented Spring Security .I have used Security config to enforce https and used below code for https redirection .
requiresChannel().anyRequest().requiresSecure()
but it gives me the following error in browser
Too many redirects occurred trying to open “https://website-name”. This might occur if you open a page that is redirected to open another page which then is redirected to open the original page.
Now I have followed few links over network inorder to enforce https where they told me to add few parameters I added these parameters in blue mix runtime environmental variables of my application.
server.tomcat.internal-proxies:.*
I also tried adding
server.tomcat.remote_ip_header:x-forwarded-for
server.tomcat.protocol_header:x-forwarded-proto
the flow of application is first go daddy lookup then it goes to the blue mix application how can i have only https enabled
But Still I get The Same error.
Guys can you help me solve this problem.
I added the custom filter
#Component
public class CustomFilter implements Filter {
private static final Logger logger = Logger.getLogger(CartController.class);
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
#Override
public void doFilter(ServletRequest request1, ServletResponse response1, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) request1;
HttpServletResponse response = (HttpServletResponse) response1;
if (!request.isSecure()) {
logger.info("Not secure");
// generate full URL to https
StringBuilder newUrl = new StringBuilder("https://");
newUrl.append(request.getServerName());
if (request.getRequestURI() != null) {
newUrl.append(request.getRequestURI());
}
if (request.getQueryString() != null) {
newUrl.append("?").append(request.getQueryString());
}
response.sendRedirect(newUrl.toString());
} else {
// already a secure connection, no redirect to https required.
logger.info("Else");
if (chain != null) {
logger.info("Chain Null");
chain.doFilter(request, response);
}
}
}
}
I would advise two options:
1. In the past I have manually implemented a filter that if a non-http request is received to redirect to https. I have not used spring security in the manner you're attempting.
2. Post a question to Rob Winch, spring security lead, on the spring forms and cross link to this question so that people on the Bluemix platform can see his response.
My initial thought is that the manual filter is the way to go but would really like to know if Rob and team have encountered this on the CF platform.
I'm considering to use OAuth2 for my application. The architecture I'm trying to implement is as follows:
I will have my own (and only this) Authorization Server
Some Resource Apps validating access to their resources using the Authorization Server
Some client apps (web, mobile) which will redirect the user to the Authorization Server for authentication and on success will consume the api's on the Resource Apps.
So far I have managed to implement this interaction between 3 basic apps (1 auth server, 1 resource server and 1 client). The thing I don't get working is the logout functionality. I have read of the "notoriously tricky problem" that Dave Syer describes in his tutorial, but in this case I really need the user to re-login after loging out. I have tried giving few seconds to the access token and the refresh token, but instead of being prompted to login again when the expiration arrives, I'm getting a NPE on the client app. I have also tried the solutions proposed in this post to remove the token from the token store, but it doesn't work. The single sign off is for me the desirable behaviour for this implementation. How can I achieve this using Spring Boot Oauth2. If it is not possible for some reason, which alternatives I could use to implement a centralized security using Spring Boot?
Thanks in advance.
After a lot of tests I have realized that this can be solved just with a redirect to the AuthServer and doing logout programmatically like this:
In the client app (WebSecurityConfigurerAdapter):
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutSuccessUrl("http://your-auth-server/exit");
}
In the authorization server:
#Controller
public class LogoutController {
#RequestMapping("/exit")
public void exit(HttpServletRequest request, HttpServletResponse response) {
// token can be revoked here if needed
new SecurityContextLogoutHandler().logout(request, null, null);
try {
//sending back to client app
response.sendRedirect(request.getHeader("referer"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
I have posted a sample app on github with a full example of this implementation.
I'm familiar with implementing BasicAuth security in Dropwizard, but only for RESTful endpoints/resources.
I am now experimenting with Dropwizard Views to see if I can use it to be both a web and REST server all in one. The web app will have "public" pages (that are really just static HTML files; "About Us", "Contact Us", etc.) as well as "private" (dynamic) pages, which really form the app. To get to these pages the user must be authenticated (logged in).
So this means I have the need for two distinct DW authentication mechanisms:
A typical DW security mechanism for authenticating REST API clients, which I'm familiar with; and
A way to implement a log in system for authenticating end users for the web app pages/resources
Ideally, I'd like Apache Shiro to handle all auth for my system (REST and web alike), and I see the Dropwizard-Shiro lib, but that seems to only authenticate REST endpoints.
My web login system need to work like so:
A user tries to go to an "authenticated" (private) URL.
A servlet filter (that I create myself and register with the environment) intercepts the request and can tell (perhaps a cookie/session var?) whether the user is authenticated or not.
If the user is authenticated, they are allowed to proceed to their intended URL ("target URL"). Otherwise they are redirected to a login page. When they login a DW resource/controller hands their credentials off to Shiro, who then decides whether the credentials are valid or not.
If the credentials are valid, they get a cookie/session var (?) and are redirected to their target URL. Otherwise they are redirected back to the login page which will now display a failure message.
My main concerns are:
* What should I implement for the cookie/session var that the servlet will check for?; and
* How do I integrate my auth controller (that is, the resource that handles redirection between the login page and the target URL) with Shiro? Is it possible to do this via that Dropwizard-Shiro lib?
My best attempt thus far:
Custom Servlet Filter (registered with environment):
public class AuthFilter implements ContainerResponseFilter {
#Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext) {
Cookie[] cookies = requestContext.getCookies();
boolean authenticated = false;
for(Cookie cookie : cookies) {
// 1. This is my first concern. What is better/more secure
// than what I'm doing here?
if("my_app_auth_cookie".equals(cookie.getName())) {
authenticated = true;
}
}
if(authenticated == false) {
responseContext.sendDirect("/auth/login");
}
}
}
If they are not authenticated they redirect to /auth/login which hits a AuthController (again, registered with the environment as a resource):
#Path("/auth")
#Produces(MediaType.TEXT_HTML)
public class AuthController {
#GET
#Path("/login")
public LoginPageView login() {
// Render some "login.ftl" template as HTML.
}
#POST
#Path("/authenticate")
public ??? authenticate(??? username, ??? password) {
// 2. Somehow send 'username' and 'password' to Shiro...
MyAppUser user = myAppRealm.authenticate(username, password);
// Now what do I do with 'user'?
}
}
When the user submits the form on the login page (which might be a POST to /auth/authenticate) we somehow hand their inputted credentials off to Shiro (again I'd like to use that Dropwizard-Shiro lib since I will likely also be using it for my REST endpoints).
Apache Shiro has its own type of filters which are configured in shiro.ini.
Example:
[urls]
/api/** = noSessionCreation, authcBasic
/views/login = authc
/views/authenticated = authc, user
Configure the authc filter to redirect to a login form page that you implement. Use the filter's form parameters and POST to /views/login.
If you enable the session manager in Jetty, Shiro should create servlet sessions when they log in from the login form page.
Please note that I haven't actually tested this configuration.