We have a JSF2.0 application deployed in weblogic-10.3.4 , we have a requirement to give a user generic url ,say (http://web/apply?7777 ) . When user access this page ,based on query string value , user will be re-directed to client specific page,which can be one of 10 different pages.
So one approach is to have a apply.jsf page ,which has got a pre-render event ,which will re-direct the user to different page based on query string,
Is there any other better approach? not to have apply.xhtml.
Note: In web.xml ,we defined pageNotFound.xhtml in case if the page is not found.
You could use a simple servlet filter for this.
#WebFilter("/apply")
public class ApplyFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String queryString = request.getQueryString();
String redirectURL = determineItBasedOnQueryString(queryString);
if (redirectURL != null) {
response.sendRedirect(redirectURL);
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
// ...
}
Related
I'm currently migrating from Spring Security SAML Extension to Spring Security SAML2 and use case requires language code to be sent in Extensions -element.
With Spring Security SAML Extension this was done by:
Extending SAMLEntryPoint and storing locale as relayState to SAMLMessageContext like this:
public class CustomSAMLEntryPoint extends SAMLEntryPoint {
private String relayState;
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException {
//read your request parameter
setRelayState(request.getParameter("locale"));
super.commence(request, response, authenticationException);
}
#Override
protected WebSSOProfileOptions getProfileOptions(SAMLMessageContext samlMessageContext, AuthenticationException authenticationException) throws MetadataProviderException {
//set the relayState to your SAML message context
samlMessageContext.setRelayState(getRelayState());
return super.getProfileOptions(samlMessageContext, authenticationException);
}
private void setRelayState(String relayState) {
this.relayState = relayState;
}
private String getRelayState() {
return relayState;
}
}
Extending WebSSOProfileImpl and using previously set relayState value to generate Extensions -element:
public class CustomWebSSOProfileImpl extends WebSSOProfileImpl {
#Override
protected AuthnRequest getAuthnRequest(SAMLMessageContext context, WebSSOProfileOptions options, AssertionConsumerService assertionConsumer, SingleSignOnService bindingService) throws SAMLException, MetadataProviderException {
AuthnRequest authnRequest = super.getAuthnRequest(context, options, assertionConsumer, bindingService);
authnRequest.setExtensions(buildExtensions(context.getRelayState()));
return authnRequest;
}
}
How could this same functionality be done with Spring Security Core SAML2? Is there some similar way than using SAMLMessageContext and relayState?
I could customize AuthenticationEntryPoint as well as authentication request creation but there seems to be no way to move locale between these two.
public AuthenticationEntryPoint authenticationEntryPoint() {
final AuthenticationEntryPoint authenticationEntryPoint = new LoginUrlAuthenticationEntryPoint(
"/saml2/authenticate/sp");
return (request, response, exception) -> {
String locale = request.getParameter("locale");
// Where shoud locale be stored???
authenticationEntryPoint.commence(request, response, exception);
};
}
#Bean
public Saml2AuthenticationRequestFactory authenticationRequestFactory() {
final OpenSamlAuthenticationRequestFactory authenticationRequestFactory = new OpenSamlAuthenticationRequestFactory();
authenticationRequestFactory.setAuthenticationRequestContextConverter(context -> {
final AuthnRequest request = new AuthnRequestBuilder().buildObject();
request.setAssertionConsumerServiceURL(context.getAssertionConsumerServiceUrl());
request.setDestination(context.getDestination());
request.setID("A" + UUID.randomUUID());
request.setIssueInstant(new DateTime());
final Issuer issuer = new IssuerBuilder().buildObject();
issuer.setValue(context.getIssuer());
request.setIssuer(issuer);
// Where can locale be read from???
request.setExtensions(buildLanguageExtensions(???);
return request;
});
return authenticationRequestFactory;
}
I use Spring Session and I am having issues with session management especially dealing with session expiration.
The idea is to return a custom Http Header to the client e.g. X-Application-Session-Is-New if the session has expired.
Here is what I came up with:
public class SessionDestroyedFilter extends OncePerRequestFilter {
//TODO: not always invoked!!
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (isAjaxRequest(request) && (isRequestedSessionInvalid(request) || isSessionNew(request))) {
response.addHeader("X-Application-Session-Is-New", "true");
}
filterChain.doFilter(request, response);
}
private boolean isRequestedSessionInvalid(HttpServletRequest request) {
return !request.isRequestedSessionIdValid();
}
private boolean isSessionNew(HttpServletRequest request) {
return request.getSession(false).isNew();
}
private boolean isAjaxRequest(HttpServletRequest request) {
return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
}
}
The issue is that my filter does not seem to be always invoked upon session expiration perhaps because the request is not an ajax request and a new session ID is immediately created after that.
Can anyone please point me to an appropriate strategy to deal with session expiration on single page apps?
EDIT Following is currently not possible (instead do decoration)
Here are some related github issues (comment on them to fix them faster)
https://github.com/spring-projects/spring-session/issues/243
https://github.com/spring-projects/spring-session/issues/112
To accomplish this you have to use your own HttpSessionStrategy.
Here is an example if you are using CookieHttpSessionStrategy (the default one)
public class CustomHttpSessionStrategy extends CookieHttpSessionStrategy {
#Override
public void onInvalidateSession(HttpServletRequest request, HttpServletResponse response) {
super.onInvalidateSession(request, response);
response.addHeader("X-Application-Session-Is-New", "true");
}
}
If you want to add your header on new sessions also consider overriding onNewSession(Session, HttpServletRequest, HttpServletResponse).
This is Wrong
Please see my other answer
You should move your logic for adding X-Application-Session-Is-New after request is processed.
Try something like
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(request, response);
if (isAjaxRequest(request) && (isRequestedSessionInvalid(request) || isSessionNew(request))) {
response.addHeader("X-Application-Session-Is-New", "true");
}
}
How do I enable URL rewriting in dropwizard? I need to rewrite all urls matching a certain pattern to /.
I'm using dropwizard 0.7.1 and I'm trying to run an Angular.js app in html5 mode in the front-end and this requires url rewriting (see https://docs.angularjs.org/guide/$location under the Server side section).
you can try with this: http://www.tuckey.org/urlrewrite/
it's very symilar to mod_rewrite.
You could add a Filter like this:
environment.getApplicationContext().addFilter(
new FilterHolder(new Filter() {
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (shouldRedirect(request.getRequestURI())) {
response.sendRedirect("/");
} else {
chain.doFilter(req, res);
}
}
#Override
public void destroy() {}
}), "/*", EnumSet.allOf(DispatcherType.class));
For simple rules it seems to me that the best option is to use the Dropwizard PathRedirect RedirectBundle.
Add dropwizard-redirect-bundle to your dependencies
Register the bundle:
#Override
public void initialize(Bootstrap<?> bootstrap) {
bootstrap.addBundle(new RedirectBundle(
new PathRedirect("/old", "/new")
));
}
It supports regular expressions as well.
Just a note that for this to work with other bundles, such as static assets and HTTPS redirect, order matters. It should be:
AssetsBundle first
HttpsRedirect second
PathRedirect last
In a grails app, I'm successfully getting the language the user has selected(added to url, "...?lang=xx_XX") like this:
def locale = RequestContextUtils.getLocale(request)
Using springsecurity, and got a special logout handler set up that works fine
grails.plugins.springsecurity.logout.handlerNames = ['securityContextLogoutHandler', 'myLogoutHandler']
I need to get the user selected locale in myLogoutHandler, but the following is not working (it only shows the browser default locale, not the one selected by the user)
class MyLogoutHandler implements LogoutHandler {
void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
def locale2 = RequestContextUtils.getLocale(httpServletRequest);
}
}
I have also tried getting the session locale with:
RequestContextHolder.currentRequestAttributes().getProperties()
but that gives the same result, anyone got an idea how to get the locale from the MyLogoutHandler?
Workaround
The session appears to be cleared by spring-security but you can still send in parameters.
so in the controller for the logout page I got:
def index = {
def myParam = "bar"
redirect(uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl + "?foo=" + myParam) // '/j_spring_security_logout'
}
And I just get the parameter in the LogoutHandler:
void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
def myParam = httpServletRequest.parameterMap.get("foo")[0]
....
}
I can get the locales by using the code below:
class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
private static final ThreadLocal<Authentication> AUTH_HOLDER = new ThreadLocal<Authentication>()
void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
AUTH_HOLDER.set authentication
// reading locales...
request.locales.each {locale ->println locale.toString()}
try {
super.handle(request, response, authentication)
}
finally {
AUTH_HOLDER.remove()
}
}
#Override
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
Authentication auth = AUTH_HOLDER.get()
String url = super.determineTargetUrl(request, response)
// do something with the url based on session data..
url
}
}
I have the following declared in my spring security configuration file (http://www.springframework.org/schema/security/spring-security-2.0.1.xsd):
<form-login login-page="/login.html" />
What Spring Security does is redirect the user to that page if they don't have the correct authentication credentials. How can I get the url of the page the user was trying to get to?
Original request is represented by the SavedRequest object, which can be accessed as a session attribute named SPRING_SECURITY_SAVED_REQUEST_KEY.
in my case i did something like this and it worked for me.
#Autowired
private LoggedUserListener loggedUserListener;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/find/**","/","/Application/**")
.access("hasRole('ROLE_USER')")
.successHandler(loggedUserListener)
//some other stuff
}
#Component
public class LoggedUserListener implements AuthenticationSuccessHandler{
#Autowired
private UserRepo userRepo;
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
HttpSession session = request.getSession();
SavedRequest savedRequest = (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST");
if(savedRequest != null) {
User u = userRepo.findByUsername(authentication.getName());
u.setLastLogin(new Date());
u.setAccountNonLocked(false);
userRepo.save(u);
response.sendRedirect(savedRequest.getRedirectUrl());
}
}
}
In Spring Security 4
The original request is represented by the DefaultSavedRequest object, which can be accessed as a session attribute named SPRING_SECURITY_SAVED_REQUEST.
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(HttpSession session) {
DefaultSavedRequest savedRequest = (DefaultSavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST");
}