Pass Spring security authentication from controller methods - java

I am using Spring MVC and Security and I have a controller with 2 methods. One creates a webpage html, and on that will take that and make a PDF out of it.
#RequestMapping(value = "/getPDFhtml", method = RequestMethod.GET)
public ModelAndView getPDFhtml(HttpServletRequest request) throws Exception {
ModelAndView modelAndView = new ModelAndView("myPDFTemplate");
// do stuff
return modelAndView;
}
#RequestMapping(value = "/createPDFFile", method = RequestMethod.GET)
public ModelAndView createPDFFile(HttpServletRequest request) {
String url = "/getPDFHtml";
String viewHtml = HttpUtil.getHttpRequest(url);
// take viewHtml and turn it into a PDF with iText
// other stuff...
}
The only way I could get this to work was to punch a hole in spring security like this (security-app-context.xml)
<intercept-url pattern="/getPDFhtml/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
because tenically, my HttpUtil call is a new sesion. (It is just a wrapper for Apache HttpClitent.jar stuff)
Now I need to not do this. I need access to the AuthenticationTolken in getPDFhtml() and it's not there because it's authenticated ananymousy, and my manager found out about my little sceuity hack and it has to go away now. :(
so I need a way to either:
be able to call getPDFhtml() from createPDFFile() and have the ModelAndView render itself into an html string. (I was told 6 months ago that this is not possable, but who knows)
be able to call getPDFhtml() from createPDFFile() and somehow pass the jsession id or the authentication token or whatever so I can get through the Spring securuity properly.
any ideas?

I went with FreeMarker.
in my main-servlet.xml I create my freemarker config:
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath"><value>/WEB-INF/freemarker/</value></property>
</bean>
#Autowired it into my controller and easy:
Template template = freemarkerConfig.getConfiguration().getTemplate("helloWorld.ftl");
template.process(data, out);
String viewHtml = out.toString();
and off to iText it goes! Thanks for all the help.

Related

Spring boot doen't retrieve form data from SAML auth

Well, I'm consuming SAML SSO created by enterprise where I work. Once user and password is typed SAML service redirects to given url as POST request, e.g.
https://some-saml-url.domine.com/idp/startSSO.ping
then fill up user and password fields and redirects to my app authentication url as POST with form data encrypted as SAMLResponse.
I'm using spring boot 2.4.5. Here my controller
#Controller
#CrossOrigin("*")
public class AuthenticationController {
#PostMapping(value = "/auth", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public String authentication(HttpServletRequest request, HttpServletResponse response) throws GasStationException {
//do something to retrieve SAMLResponse
return "redirect:/";
}
}
I'm able to catch request inside controller but not to get form data. I've tried multiple solutions I've found through internet but nothing. Hope somebody have an idea or solution that helps me.
Ok, if somebody have this kind of issue and is using logbook, well that's why. In logback file I have this one
<logger name="org.zalando.logbook" level="TRACE" />
And don't know why logbook takes form data values print them in console and delete them from request. After comment this line all works.

Preserving model state with Post/Redirect/Get pattern and URL rewriting

First of all, I know that there are similar questions regarding "Preserving model state with Post/Redirect/Get pattern", but none of these have my very specific problem:
background:
My Code is working in an enterprise CMS software which does a lot of things. One of them is URL rewriting: Whenever I generate Links to my controller, dependending on the environment, the links are shortened - That's a SEO thing and can't be discussed.
I.e. if my Controller URL is /webapp/servlet/myController/doSomething, the generated URL will be /myController/doSomething. There's some LinkProcessing functionality that we have to use.
An apache rewrite rule will then expand this short url to /webapp/servlet/myController/doSomething when the apache uses mod_rewrite to call the corresponsing code on the tomcat:
RewriteCond %{REQUEST_URI} ^/myController/(.*)
RewriteRule ^/myController/(.*) /webapp/servlet/myController/$1 [PT,L]
Problem:
I'm trying to implement the Post/Redirect/Get pattern using Spring 3.1.2. I'm generating a form and POST it to the Controller, which validated and makes a redirect to either the success or error page using GET (Post/Redirect/Get pattern).
(highly simplified) Code:
#RequestMapping()
public class MyController {
#RequestMapping(value = "/doDispatch", method = RequestMethod.POST)
public RedirectView handleDispatch(RedirectAttributes redirectAttributes,
#Validated #ModelAttribute FormBean formBean,
BindingResult binding) {
if (binding.hasErrors()) {
redirectAttributes.addFlashAttribute(formBean);
redirectAttributes.addFlashAttribute(BindingResult.MODEL_KEY_PREFIX+"formBean", binding);
return new RedirectView(generateLink("/error"));
} else {
redirectAttributes.addFlashAttribute(formBean);
redirectAttributes.addFlashAttribute(BindingResult.MODEL_KEY_PREFIX+"formBean", binding);
return new RedirectView(generateLink("/success"));
}
}
#RequestMapping(value = "/success")
public ModelAndView handleSuccess(#ModelAttribute FormBean formBean) {
// do stuff (save things in the DB)
// ...
final ModelAndView modelAndView = createModelAndView(formBean);
modelAndView.addObject("success", true);
return modelAndView;
}
#RequestMapping(value = "/error")
public ModelAndView handleError(#Validated #ModelAttribute FormBean formBean,
BindingResult binding) {
final ModelAndView modelAndView = createModelAndView(formBean);
modelAndView.addObject("binding", binding);
modelAndView.addObject("formBean", formBean);
return modelAndView;
}
}
The problem ist that this generateLink() method will either generate links starting with /webapp/servlet or not - depending on the environment/success. And that's how this whole Enterprice CMS thing works. (that's the part which cannot be discussed)
Spring Flash-Attributes on the other hand work hand in hand with the URLs that are returned and store the URL as part of the FlashMap:
Quote from http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-flash-attributes :
To reduce the possibility of such issues, RedirectView automatically "stamps" FlashMap instances with the path and query parameters of the target redirect URL. In turn the default FlashMapManager matches that information to incoming requests when looking up the "input" FlashMap.
Since the next request (let's say I've had an error and returned "/myController/error") will be expanded to /webapp/servlet/myController/error, the FlashMap will not apply to this request, since the URLs do not match.
The code that is responsible is this here (AbstractFlashMapManager.java:157 ff):
protected boolean isFlashMapForRequest(FlashMap flashMap, HttpServletRequest request) {
if (flashMap.getTargetRequestPath() != null) {
String requestUri = this.urlPathHelper.getOriginatingRequestUri(request);
if (!requestUri.equals(flashMap.getTargetRequestPath())
&& !requestUri.equals(flashMap.getTargetRequestPath() + "/")) {
return false;
}
}
// ...
}
Question:
Do you know a way how I can still generate short URLs on the one hand, but pass the FlashAttributes to the following GET request?
Best regards and thanks for your help in advance,
Alexander
The best solution I've found so far is using an Interceptor that updates the targetRequestPath by prefixing /<webappPath>/<servletPath> to those FlashMaps from RequestContextUtils.getOutputFlashMap(request) that are missing this information. BTW: this can only be done in the afterCompletion method, because otherwise the targetRequestPath won't be set at all, when using a RedirectView.
Any other, better solutions?

Model model in Controller's method parameters in Spring MVC

This may be a very naive question to ask but I would like to know as a beginner in Spring MVC framework instead of returning ModelAndView Object can we just return a jsp name from a Controller's method definitions ? Also Apparently all the methods seem to take Model model as a argument. What does they mean ?
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.debug("Entering renderShoeStoreApplication method");
//model.addAttribute("orderList", orderList);
logger.debug("Exiting renderShoeStoreApplication method");
return "home";
}
Instead of we could also write I suppose
/*
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model) {
logger.debug("Entering renderShoeStoreApplication method");
//model.addAttribute("orderList", orderList);
logger.debug("Exiting renderShoeStoreApplication method");
ModelAndView homeModel = new ModelAndView("home");
return homeModel ;
}*/
Please explain the basics . Thanks in advance.
i think you have got two question
All the methods seem to take Model model as a argument
this is necessarily not required, you can get http request as param and you can derive your model from the request parameters. eventually spring mvc does this for you to make the work much simpler using binding-result after bean validation.
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, HttpRequest request) {
String name = request.getParamter("name");
// you can manually derive your model here
}
can we just return a jsp name from a Controller's method definitions ?
you can pass the just jsp name in your controller method, provided if you have configured your view resolver to handled this.
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
if you return string from controller, by default controller direct to view resolver to resolve the view. pls check this SO post
You can go through the below resources to understand the basics of Spring MVC, first and foremost the official docs from spring MVC community and some of the quick heads up of the POC's using below links
http://earldouglas.com/publications/barebones-spring-mvc/
http://spring.io/guides/gs/serving-web-content/
http://www.mkyong.com/tutorials/spring-mvc-tutorials/
Why model is passed as a parameter to controller method and what is the purpose of ModelView object?..All such questions will get answered once you will get the basic understanding of Spring MVC architecture.
And Yes, In the event that there isn't any data to be returned by the method, the controller method can simply return a String that represents the view that should be rendered.

How to return a variable in every page from my Spring MVC application from the same controller method?

I want to return a model from my Spring MVC controller, which will be visible to all pages in my application.
So, I need a variable which return some user details.
This is my code:
#RequestMapping(value = "/*", method = RequestMethod.GET)
public void status(Model model){
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
String username = auth.getName();
Manager mgr = managerService.findOne(username);
model.addAttribute("buget", mgr.getTeam().getTeamBuget());
}
And in my jsp page, i write something like this:
<li> <c:out value="${buget}" /> <span class="glyphicon glyphicon-euro"></span></li>
I want to be able to print the ${buget} in every page from my app.
So, my method don't work, nothing is appear in my pages and the biggest problem
for me is that I don't get any exceptions or errors which could help me. Who can help me with some advices?
I'm not entirely sure what it is that you're trying to do. Do you mean that you want buget to be part of every page that you hit? If so, you have to insert it into the model. Based on your code, I'm assuming that you have the mistaken impression that status is going to be called regardless of whatever page you hit. Spring will resolve to the most-specific handler and so if you have another handler method in another controller that is more specific, Spring will use that. But even if the one you have was called, how would Spring know that it has to call the most-specific one next? So how would you add page-dependent model attributes to the model?
If you want buget to be part of every response, you can use #ControllerAdvice (see here for a blog post with more details):
#ControllerAdvice
public class BugetControllerAdvice {
#ModelAttribute
public void addBugetToModel(Model model) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName();
Manager mgr = managerService.findOne(username);
model.addAttribute("buget", mgr.getTeam().getTeamBuget());
}
}
Spring will now call this method before every handler-method in every controller. You can also take a look at the Spring Reference for more information.

spring json not working

I created a controller with method handler as
#RequestMapping( value = {"/membersjson"},method = RequestMethod.GET)
public #ResponseBody String getMembers(Model model) {
List<Member> members = memberService.getMembers();
model.addAttribute("members",members);
return "jsontemplate";
}
<bean id="jsontemplate"
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
I expect the out put to be in json but instead the output is "jsontemplate" instead. Can some one please explain the reason. thanks in advance.
MappingJacksonJsonView, or any other view or view resolver bean, is irrelevant when you're using #ResponseBody. Instead, Spring will try to convert the return value of your method directly into a response. In this case, it's decided to turn it into a String response.
First make, sure you've declared <mvc:annotation-driven/> in your context, and that Jackson is available on the classpath. Also ensure that the browser is sending application/json in its Accept header.
You shouldn't be returning the string "jsontemplate"; you should return either the List<Member> or the Model. The json mapping should occur automatically.

Categories

Resources