Showing posts with label Spring. Show all posts
Showing posts with label Spring. Show all posts

Saturday, 4 December 2021

This week 3/2021 - springSecurity Rest basic controller

In this short post I'd like to present a simple configuration of Spring Boot application serving stateless service using basic authentication.

Below a web security configurer implementation including all possible ways to define annotation rule matchers (pre, post processing and jsr250 specification)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
@EnableGlobalMethodSecurity(
        prePostEnabled = true,
        securedEnabled = true,
        jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(final HttpSecurity http) {
        sessionSettings()
                .andThen(this::headersSecurity)
                .andThen(this::accessRules)
                .unchecked()
                .accept(http);
    }

    private void headersSecurity(final HttpSecurity http) throws Exception {
        http.sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .csrf()
            .disable()
            .httpBasic()
            .realmName("App");
    }


    private CheckedConsumer<HttpSecurity> sessionSettings() {
        return http -> http
                .sessionManagement()
                .sessionCreationPolicy(STATELESS);
    }

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("client")
                .password(passwordEncoder().encode("admin"))
                .roles("CLIENT");
    }
...
}

What is important in code is to define session creation policy.

Then it is possible to implement standard resource.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@RestController
@RequestMapping("/service")
public class Endpoint {

    @PostMapping("/endpoint")
    @Secured("ROLE_CLIENT")
    public String endpoint(@RequestBody final String req) {
        return "test";
    }
}

Resources:

[1] - Spring Security

Sunday, 29 December 2019

This week 3/2019 - WebApp with Spring Security

Yesterday I did small exercise. I upgraded one of my old applications from xml (web.xml) configuration to class version as a first step to later upgrading.
There was no problems until I run application and all world could see everything what only an authorized user should see.

I couldn't find simple example which I could I adopt to my needs so I decided to describe this by my self.

Some examples proposed to extend AbstractSecurityWebApplicationInitializer, other proposed to import just import security configuration but it wasn't work as I expected. I created servlet initializer as below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class StockDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

  @Override
  protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[]{MySecurityConfig.class, MyRootConfig.class};
  }

  @Override
  protected Class<?>[] getServletConfigClasses() {
    return new Class<?>[]{MyServletConfig.class};
  }

  @Override
  protected String[] getServletMappings() {
    return new String[]{"/"};
  }

  protected Filter[] getServletFilters() {
    return new Filter[]{new DelegatingFilterProxy("springSecurityFilterChain")};
  }

}


MySecurityConfig I extended with WebSecurityConfigurerAdapter and implemented configure method as below:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@EnableWebSecurity
@Configuration
@ComponentScan("org.my")
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  private final MyLogoutSuccessHandler myLogoutSuccessHandler;
  private final MyAuthenticationProviderImpl myAuthenticationProvider;

  public SecurityConfig(final MyLogoutSuccessHandler myLogoutSuccessHandler,
                        final MyAuthenticationProviderImpl myAuthenticationProvider) {
    this.myLogoutSuccessHandler = myLogoutSuccessHandler;
    this.myAuthenticationProvider = myAuthenticationProvider;
  }


  @Autowired
  public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(myAuthenticationProvider);
  }

  @Override
  public void configure(final WebSecurity web) {
    web.ignoring()
       .antMatchers("/css/**")
       .antMatchers("/img/**");
  }


  @Override
  protected void configure(final HttpSecurity http) throws Exception {
    formLogin(http);
    logout(http);
    headers(http);
    authorizeRequests(http);
    sessionManagement(http);
  }
.......
}


MyServletConfig looks like


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@EnableWebMvc
@Configuration
@ComponentScan({"org.**.mvc"})
public class StockServletConfig implements WebMvcConfigurer {

  @Override
  public void addResourceHandlers(final ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/img/**").addResourceLocations("/img/");
    registry.addResourceHandler("/css/**").addResourceLocations("/css/");
  }

  @Bean
  ViewResolver viewResolver() {
    return new InternalResourceViewResolver("/WEB-INF/jsp/", ".jsp");
  }

  @Bean
  PropertiesFactoryBean propertiesFactoryBean() {
    final PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
    propertiesFactoryBean.setLocation(new ClassPathResource("version.properties"));
    return propertiesFactoryBean;
  }

  @Bean
  ObjectMapper customObjectMapper() {
    return new CustomObjectMapper();
  }

  @Bean
  LocaleResolver localeResolver() {
    final SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
    sessionLocaleResolver.setDefaultLocale(ENGLISH);
    return sessionLocaleResolver;
  }

  @Bean
  public LocaleChangeInterceptor localeChangeInterceptor() {
    final LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
    localeChangeInterceptor.setParamName("lang");
    return localeChangeInterceptor;
  }

  @Override
  public void addInterceptors(final InterceptorRegistry registry) {
    registry.addInterceptor(localeChangeInterceptor());
  }

  @Override
  public void configureMessageConverters(final List<HttpMessageConverter<?>> messageConverters) {
    messageConverters.add(new MappingJackson2HttpMessageConverter(customObjectMapper()));
  }
}


Now I am analysing MyServletConfig and it is possible to do it other way - by adding some specific interceptor. Nevertheless current solution works:)

Any other better ideas ???

--
I used in example Spring/Spring Security 5.2.1 and Apache Tomcat 8.5.50

Wednesday, 3 May 2017

This week 9/2017 - The REST client API

There are a few implementation of REST client for Java. I will compare 3, I think, most popular implementations.
  1. Jersey (v. 2.25.x)
  2. Spring Web (v. 3.2.x)
  3. Apache CXF (v. 3.0.x)
My goal is to create component which can:
  1. Connect by secure channel - SSL
  2. Authentication bu Basic authorization mechanism.
  3. Send custom message.
  4. Read response and deserialize it into object.
So most common use of client. I was pointing to: flexible interface, clean code - nothing special. So I created following Java code


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.util.Arrays;
import java.util.Base64;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import org.apache.cxf.jaxrs.client.WebClient;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

public class App {

 // Apache CXF
 private static WebClient createWebClient() {
  return WebClient.create(getUrl(), "aa", "bbc", null);
 }
 private void testWebClient(){
  System.out.println("\n\ntestWebClient:");
//  System.out.println(createWebClient().path("todo22").accept(MediaType.TEXT_XML).get(Todo2.class));
  System.out.println(createWebClient().path("todo22").get(Todo2.class));
  System.out.println(createWebClient().path("todo22").get(String.class));
 }

 // Jersey
 private static Client createWebTarget() {
  HttpAuthenticationFeature authenticationFeature = HttpAuthenticationFeature.basic("aa", "bbc");
  return ClientBuilder.newBuilder().newClient().register(authenticationFeature);
 }

 private void testWebTarget(){
  WebTarget service = createWebTarget().target(getUrl());
  System.out.println("\n\ntestWebTarget :");
//  System.out.println(service.path("todo22").request(MediaType.TEXT_XML).get(Todo2.class));
  System.out.println(service.path("todo22").request().get(Todo2.class));
  System.out.println(service.path("todo22").request().get(String.class));
 }

 // Spring Web Rest
 private static HttpHeaders getHeaders(){
  String plainCredentials="aa:bbc";
  String base64Credentials = new String(Base64.getEncoder().encode(plainCredentials.getBytes()));

  HttpHeaders headers = new HttpHeaders();
  headers.add("Authorization", "Basic " + base64Credentials);
  headers.setAccept(Arrays.asList(org.springframework.http.MediaType.TEXT_XML));
  return headers;
 }

 private void testRestTemplate(){
  System.out.println("\n\ntestRestTemplate :");
  RestTemplate restTemplate = new RestTemplate();

  // restTemplate.getMessageConverters().add(new MappingJacksonHttpMessageConverter());
  restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
  HttpEntity<String> request = new HttpEntity<String>(getHeaders());
  System.out.println(restTemplate.exchange(getUrl() + "todo22", HttpMethod.GET, request, Todo2.class).getBody());
  System.out.println(restTemplate.exchange(getUrl() + "todo22", HttpMethod.GET, request, String.class).getBody());
 }

In my opinion the simplest interface has Apache CXF but you need to remember to create new instance for multiple services.
Jersey interface looks to be it most powerful. At the beginning there is created some service client template - core of client. Then every time when path method is executed there is created new instance of client with resource name.
Jersey support all kind of authentication methods providing tool. It is opposite to Spring Web RestTemplate where I had to prepare manually authorization header. Spring Web REST required much more code then two other solutions.

Resources:

Tuesday, 18 April 2017

This week 7/2017

Spring Boot (v. 1.5.x) is a project which supports developer in creating and boot application. Application created by it integrates with long technology stack list mentioned in project reference guide.
Creation of complex application is very easy. Developer add dependences of starter artefact and application should work with default settings. If he need to change defaults, he can add properties file, add custom annotation or set custom settings in code.
Simple application is ready in a few seconds, there is needed only a custom pom or gradle file and writing a few lines of code - simple class with annotation
@EnableAutoConfiguration
and main method in which is execution of run method of the SpringApplication class.
If there is needed a web application, it is not a problem. Spring Boot supports three web containers Tomcat/Jetty/Undertow. If there is needed something else probably it is not a problem as well list is truly long.

Spring Boot contains additional development tools supporting Http caching, automatic restart of application after source update and few less important things for me. 
In my case, I was most interested in automatic restart and hot swapping. DevTools don't contain solution as good as JRebel and Spring Loaded because they don't reload byte code during runtime but restart part of application. This solution splits class path on the unchangeable paths and changeable. This first is loaded by standard class loader. The second is loaded by loader which is removed during restart and created new one. It is possible to choose jar files which should be replaced during restart.

Spring Boot support loading configuration parameters (@ConfigurationProperties) and validate them during application start.

In the end I can add that there is a page with an application creator. Generator create pom/gladle file with selected technology stack and sample code.