Spring custom login page only showing in IDE - spring-mvc

I am developing a REST-API with Spring Boot. Now I want to act as a OAuth2 provider as well and therefore I want to add support for the "client_credentials" grant type.
In order to do that I have to allow users to login and authorize the client. Spring provides an ugly default login form for doing that so now I want to show my own custom login form instead.
The problem is I can't get it to work outside my IDE.
My configuration looks as follows:
#Configuration
#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher("**/login")).and().authorizeRequests().antMatchers("/hellopage").hasAuthority(Role.USER.value())
.and().formLogin().defaultSuccessUrl("/hellopage").loginPage("/login").and().logout().permitAll();
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/*.css");
web.ignoring().antMatchers("/*.js");
}
}
#Configuration
protected class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/*.js/**").addResourceLocations("/ui/static/");
registry.addResourceHandler("/*.css/**").addResourceLocations("/ui/static/");
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/login").setViewName("login");
registry.addViewController("/testpage").setViewName("testpage");
registry.addViewController("/hellopage").setViewName("hellopage");
}
#Bean
public InternalResourceViewResolver setupViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/ui/jsp/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
And my folder structure looks like this:
When I run my application inside Eclipse and visit http://localhost:8080/login everything works fine and my custom login form is shown. When I package my application with maven and execute the generated .war file, visiting http://localhost:8080/login shows the ugly default login form which leads me to believe that spring is unable to find the resources for my custom form.
When I try to access any other .jsp like testpage.jsp, I get the following error (this also works fine when the app is run from my IDE):
I am deploying my application using a docker container that runs the .war file using java -jar myserver.war, so this has to work for me.
How can I make sure Spring can find my provided resources when executing the .war file?

By default Maven expects a the jsp's in /WEB-INF/* location.
You can keep the jsp's in src/main/webapp/WEB-INF/jsp. Also you can update the InternalViewResolver prefix as well accordingly.
For detailed explanation you can refer https://stackoverflow.com/a/19786283/3981536

Related

Static resources are not being served

I want to serve static resources in my spring web MVC application. In this project, I am using annotation based configuration, but static resources are not getting served. I tried from both side:
1st way
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/resources/");
}
2nd way
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
If you use SpringBoot default configuration you can access static resource from default web route. For example http://yourhost:8080/images/test.jpg where images is a a folder in the static branch.

Problem with my mvc app isnt using style.css

Im trying to configure style css file with my mvc app. Everything is working well except that pages dont use style.css. Im doing it first time and i dont know how it should look like but i did this with internet. Where is a problem? :/
App config
#Configuration
#EnableWebMvc
#EnableTransactionManagement
#ComponentScan("spring")
#PropertySource({ "classpath:persistence-mysql.properties" })
public class AppConfig implements WebMvcConfigurer {
#Autowired
private Environment env;
private Logger logger = Logger.getLogger(getClass().getName());
#Bean
public InternalResourceViewResolver viewResolver()
{
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/views/");
return viewResolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
Head JSP file
<head>
<title>Site under construction</title>
<link href='<spring:url value="/resources/css/style.css"/>'>
</head>
Path to css file
\src\main\resources\css\style.css
Bring up the debug tools in your browser (F12 generally). You will most likely see a 404 for that file (missing). Check out what URL the browser is trying to pull the resource from. Most likely it's looking somewhere you aren't expecting.

Integrate vertex with existing spring web application

I have an existing Spring based web application. I want to integrate vertx within the application.
Is there a way to do so?
Yes, have a look at the Vert.x with Spring section in the examples repository on GitHub.
In spring boot it is fairly simple
#SpringBootApplication
#ComponentScan(basePackages = { "com.mypackage", "com.myotherpackage" })
public class MyApplication {
#Autowired
private MainVerticle mainVertical;
public static void main(String[] args) throws Exception {
new SpringApplication(MyApplication.class).run(args);
}
#PostConstruct
public void deployServerVerticle() {
Vertx.vertx().deployVerticle(mainVertical);
}
}
The #PostConstuct allows you to deploy all the verticals you want (all the properties are set at this point).
And it goes without saying that the MainVerticle should be marked with the #Component annotation.

Adding a custom filter to be invoked after spring-security filter in a Servlet 3+ environment

I'm using Spring-Security 3.2.4 and Spring Boot 1.1.0 (and it's related dependencies versions 4.X).
I'm writing a web application that will be run in an embedded tomcat.
I'm trying to add two additional filters(not related to Spring security) that one of them will be invoked before the Spring-Security-FilterChainProxy and the other one will be invoked after the Spring-Security-FilterChainProxy.
My Spring-Security configuration files:
#Configuration
#EnableWebMvcSecurity
public class SecurityCtxConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("pass").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.usernameParameter("user").passwordParameter("password");
}
}
And the Main class (Application.class):
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application {
#Bean
RequestFilter beforeSpringSecurityFilter(){
return new RequestFilter();
}
#Bean
RequestFilter afterSpringSecurityFilter(){
return new RequestFilter();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And the Filter implementation:
public class RequestFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(request, response);
}
}
Is there a way to controll the invocation order when taking in account the FilterChainProxy (that is beeing created by the WebSecurityConfigurerAdapter ?
To be percise, the required order is:
request-filter-1
Spring-Security FilterChain
request-filter-2
Thanks
Agree with everything stated by Dave Syer ;) but wished to add a Java Config example of using the FilterRegistrationBean.
In my situation, I was finding that my custom security filter (using Spring Security) was being fired twice for every request. Adding the FilterRegistrationBean config fixed this.
#Bean(name = "myFilter")
public MyAuthenticationFilter myAuthenticationFilter(final MyAuthenticationEntryPoint entryPoint) {
final MyAuthenticationFilter filter = new MyAuthenticationFilter();
filter.setEntryPoint(entryPoint);
return filter;
}
/**
* We do this to ensure our Filter is only loaded once into Application Context
*
*/
#Bean(name = "authenticationFilterRegistration")
public FilterRegistrationBean myAuthenticationFilterRegistration(final MyAuthenticationFilter filter) {
final FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(filter);
filterRegistrationBean.setEnabled(false);
return filterRegistrationBean;
}
(Regarding my specific issue of filter being registered twice in Application Context - Rather than using a FilterRegistrationBean, I also found re-implementing the MyAuthenticationFilter to inherit from OncePerRequestFilter instead of GenericFilterBean also worked. However, OncePerRequestFilter support is from Servlet 3.x upwards and since I was writing a public library, support from Servlet 2.x may be needed)
The FilterChainProxy use by Spring Security is not Ordered (if it was you could order all your filters). But you should be able to register it in a FilterRegistrationBean which is Ordered and register your other filters the same way. In the case of the security filter you can inject it by name into the registration bean. The others you can probably inject by calling a #Bean method.
At some point spring boot exposed the security filter as a property. This is now pretty easy to do.
In you application.yml:
spring:
security:
filter:
order: 20
And some filter you want to invoke after Spring Security does it's thing:
#Bean
public FilterRegistrationBean<Filter> afterAuthFilterRegistrationBean() {
FilterRegistrationBean<Filter> registrationBean = new FilterRegistrationBean<>();
//a filter that extends OncePerRequestFilter
AfterAuthFilter afterAuthFilter = new AfterAuthFilter();
registrationBean.setFilter(afterAuthFilter);
//this needs to be a number greater than than spring.security.filter.order
registrationBean.setOrder(30);
return registrationBean;
}
For a filter that is executed before Spring security, set the order to a number less than 20.
If you are using web.xml approaches, you can follow this:
https://stackoverflow.com/a/11929129/1542363
If you using Java config approaches, you can do this in WebSecurityConfigurerAdapter
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(your-request-filter-1, ChannelProcessingFilter.class);
http.addFilterAfter(your-request-filter-2, SwitchUserFilter.class);
}
Always check the library version you are using, and refer to the specific document for the correct order of the filter chains:
https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#ns-custom-filters
Or, if you using AbstractSecurityWebApplicationInitializer, you can use the insertFilters or appendFilters.
public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
#Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
insertFilters(servletContext, new MultipartFilter());
}
}
More info You can refer this:
https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#csrf-multipart

Configuring spring to return a static file on a Controller method

How do I say to Spring MVC to return a static resource at runtime(in a method)?
Explain better. I configured my application(spring-mvc 3.2.4) to deal with some static resource and to work with two view resolvers, FreeMaker and Json. I wish that in a controller method I would be able to say to spring-mvc that he must take the file in the static resource despite try hadle by one of views resolvers.
My configuration class looks like this:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.xxxx", excludeFilters = #Filter(Configuration.class)})
public class WebConfig extends WebMvcConfigurerAdapter {
...
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/app.js").addResourceLocations("/app.js");
}
...
#Bean
public ViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
// Define the view resolvers
List<ViewResolver> resolvers = new ArrayList<ViewResolver>();
JsonViewResolver jsonViewResolver = new JsonViewResolver();
FreeMarkerViewResolver freeMarkerViewResolver = new FreeMarkerViewResolver();
freeMarkerViewResolver.setSuffix("rtl");
resolvers.add(jsonViewResolver);
resolvers.add(freeMarkerViewResolver);
ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
resolver.setContentNegotiationManager(manager);
resolver.setViewResolvers(resolvers);
return resolver;
}
}
My controller:
#Controller
#RequestMapping("/")
public class JSViewController {
#RequestMapping(value="*.js")
public String resolveArquivo(HttpServletRequest request){
// Here I would be able to say to sprint to return a static resource instead of hadle it with one of the View Resolvers.
return request.getRequestURI().replace(request.getContextPath(),"");
}
}
Its would be better if you try to access static and dynamic data seperately as hitting a controller for static data will waste your resources, increase latency.
For eg. if you want to access js from jsp then you can use JSTL tag library which would dynamically return the output directory from where you can fetch the static resource.
This gives you the flexibility to cache your static resources (Akamei or something else) or server them from apache instead of tomcat.
If you really want to render your static resource from controller then you need to have an interceptor which could be called before any of the view resolvers which will identify whether the requested resource us static and render accordingly. But this would be invoked for every htttp request which is not desirable.
Unfortunately I wasn't able to figure out how return a static resource in runtime with spring, but I resolved the situation using the old and good Filter.

Resources