HTTPS Authentication with Spring Security.

0

Простой пример использования HTTPS аутентификации. Spring Security, Spring MVC, Spring Boot.

Традиционный Application.java.

package ua.com.computerman.hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) throws Throwable {
        SpringApplication.run(Application.class, args);
    }

}

Настройки embedded сервлет-контейнера EmbeddedServletContainerConfig.java.

package ua.com.computerman.hello;

import org.apache.catalina.connector.Connector;
import org.apache.coyote.http11.Http11NioProtocol;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

@Configuration
public class EmbeddedServletContainerConfig {
    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
        tomcat.addAdditionalTomcatConnectors(createSslConnector());
        return tomcat;
    }

    private Connector createSslConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
        try {
            File keystore = getKeyStoreFile();
            File truststore = keystore;
            connector.setScheme("https");
            connector.setSecure(true);
            connector.setPort(8443);
            protocol.setSSLEnabled(true);
            protocol.setKeystoreFile(keystore.getAbsolutePath());
            protocol.setKeystorePass("changeit");
            protocol.setTruststoreFile(truststore.getAbsolutePath());
            protocol.setTruststorePass("changeit");
            protocol.setKeyAlias("apitester");
            return connector;
        } catch (IOException ex) {
            throw new IllegalStateException(
                "cant access keystore: [" + "keystore" + "] or truststore: [" + "keystore" + "]",
                ex
            );
        }
    }

    private File getKeyStoreFile() throws IOException {
        ClassPathResource resource = new ClassPathResource("keystore");
        try {
            return resource.getFile();
        } catch (Exception ex) {
            File temp = File.createTempFile("keystore", ".tmp");
            FileCopyUtils.copy(resource.getInputStream(), new FileOutputStream(temp));
            return temp;
        }
    }
}

Незатейливая конфигурация Spring MVC.

package ua.com.computerman.hello;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
    
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
        registry.addViewController("/ok").setViewName("ok");
    }

}

WebSecurityConfig.java.

package ua.com.computerman.hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .requiresChannel()
            .antMatchers("/login").requiresSecure()
            .antMatchers("/**").requiresInsecure()
            .and()

            .authorizeRequests()
            .antMatchers("/", "/home").permitAll()
            .antMatchers("/**").fullyAuthenticated()
            .and()
            // Original: http://stackoverflow.com/q/28341645/285571
            .sessionManagement().sessionFixation().none()
            .and()

            .formLogin().loginPage("/login").permitAll().failureUrl("/login")
            .permitAll().and().logout().logoutUrl("/logout").permitAll().logoutSuccessUrl("/")
            .permitAll()
            // Disable CSRF for making /logout available for all HTTP methods (POST, GET...)
            .and().csrf().disable();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
            .withUser("user").password("user").roles("USER");
        auth
            .inMemoryAuthentication()
            .withUser("guest").password("guest").roles("USER");

    }
}

Шаблоны thymeleaf, подробнее о них тут.

hello.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
        <p>Click <a th:href="@{/ok}">here</a> to visit the OK page.</p>
        <form th:action="@{/logout}" method="post">
            <input type="submit" value="Sign Out"/>
        </form>

    </body>
</html>

home.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example</title>
    </head>
    <body>
        <h1>Welcome!</h1>
        
        <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
    </body>
</html>

login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example </title>
    </head>
    <body>
        <div th:if="${param.error}">
            Invalid username and password.
        </div>
        <div th:if="${param.logout}">
            You have been logged out.
        </div>
        <form th:action="@{/login}" method="post">
            <div><label> User Name : <input type="text" name="username"/> </label></div>
            <div><label> Password: <input type="password" name="password"/> </label></div>
            <div><input type="submit" value="Sign In"/></div>
        </form>
    </body>
</html>

ok.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
    <title>Ok</title>
</head>
<body>
    <h1 th:inline="text">Ok [[${#httpServletRequest.remoteUser}]]!</h1>
    <p>Click <a th:href="@{/hello}">here</a> to back the hello page.</p>
    <form th:action="@{/logout}" method="post">
        <input type="submit" value="Sign Out"/>
    </form>

</body>
</html>

Код на GitHUB.

The simplest REST service.

0

Благодаря сочетанию Spring Boot и Spring MVC, простейший REST сервис можно сделать за пару минут, Для этого понадобится всего два класса по паре строк кода и минимальный pom.xml.

Простой контроллер AnswerController.java.

package ua.com.computerman.loony;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AnswerController {
    @RequestMapping("/")
    public String answer() {
        return "It works!";
    }
}

Главный класс приложения Application.java.

package ua.com.computerman.loony;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application extends SpringBootServletInitializer { 
    public static void main(String[] args) { 
        SpringApplication.run(Application.class, args); 
    } 
} 

Наследование от SpringBootServletInitializer не обязательно для запуска через Spring Boot, таким образом мы получаем возможность ручного развертывания .war файла на локальном сервлет-контейнере, если потребуется.

Незамысловатый pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>ua.com.computerman</groupId>
    <artifactId>LoonyREST</artifactId>    
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.7.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

Примечательно, что для запуска приложения нет необходимости развертывать что-либо в сервлет-контейнер — Spring Boot использует по умолчанию embeded Tomcat 8.0.
После запуска появится возможность сразу обращаться к http://localhost:8080/ в браузере, в ответ вернется текст «It works!».

Код на GitHUB.

Перевод «JUnitBenchmarks: Tutorial».

0

timer

Оригинал: тут.

JUnitBenchmarks: Учебник.

Быстрый старт.
В овладении JUnitBenchmarks есть два ключевых элемента: аннотации и системные свойства, к счастью, большинство из них являются необязательными и требуются только для достижения специфических целей.

Превратите ваши JUnit4 тесты в тесты производительности.
Предполагается, что ваш класс уже является тестом Junit4. Например, предположим, что ваш тестовый класс выглядит следующим образом:

public class MyTest {
  @Test
  public void twentyMillis() throws Exception {
    Thread.sleep(20);
  }
}

Чтобы превратить этот тест в тест производительности, вам необходимо добавить правило для JUnit4 (rule), которое сообщит исполнителям тестов JUnit4 о необходимости прикрепить измерительный код к вашему тесту. Добавить такое правило легко, просто добавьте соответствующее поле, как в нижеследующем примере (строки с импортом опущены): Continue reading