Привет, хабрахабр!
На данный момент тут уже довольно много гайдов по такой связке, но они на мой взгляд во-первых немного устаревшие, во вторых — я считаю что должен быть гайд как сделать что-то осязаемое но простое, чтобы показать что и такое возможно 🙂
Итак, если вам хочется попробовать Spring MVC со сохранением в базе и 0(нулем) файлов xml-конфигураций, прошу под кат!
1. Подготовка к запуску
1.1 IDE
1.2 Структура папок
1.3 Gradle & Git
1.3.1 Для остальных
1.4 База данных
2. Начинаем кодить
2.1 Создание проекта
2.2 Добавляем первый код
2.3 Контент
3. Добавляем работу с БД
3.1 Сущность «User»
3.2 Репозиторий UsersRepository
3.3 Добавление связи между юзером и Spring Security
4. К чему мы пришли
4.1 Для желающих запустить готовый проект
Конечно хотелось бы сразу запустить приложение, но сначала немного подготовимся.
1. Подготовка к запуску
1.1 IDE
Вся разработка будет вестись на Intellij IDEA, но не думаю что реализация в другой IDE будет сильно сложнее.
1.2 Структура папок
Сначала создадим папку проекта, назовем ее ForHabrahabr
Для нашего проекта в корне нужно создать вот такое дерево папок:
(можно же просто сделать по инструкции для остальных в следующем разделе)
1.3 Gradle & Git
Теперь добавим в него контроль версий и сборщик.
Для этого в ForHabrahabr добавим .gitignore с вот таким содержанием
.idea
*.iml
build/
Заходим в эту директорию через консоль и пишем
git init
Теперь добавим bulid.gradle со всеми зависимостями которые нам пригодятся в процессе написания приложения.
repositories {
mavenCentral()
}
dependencies {
classpath(«org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE»)
classpath ‘mysql:mysql-connector-java:5.1.34’
}
}
apply plugin: ‘java’
apply plugin: ‘eclipse’
apply plugin: ‘idea’
apply plugin: ‘spring-boot’
jar {
baseName = ‘gs-rest-service’
version = ‘0.1.0’
}
repositories {
mavenCentral()
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile(«org.springframework.boot:spring-boot-starter-web»)
compile(«org.springframework.boot:spring-boot-starter-data-jpa»)
compile(«org.springframework.boot:spring-boot-starter-security»)
compile(«org.springframework.boot:spring-boot-starter-thymeleaf»)
compile ‘mysql:mysql-connector-java:5.1.31’
compile ‘commons-dbcp:commons-dbcp:1.4’
testCompile(«org.springframework:spring-test»)
testCompile(«junit:junit»)
testCompile ‘org.springframework.security:spring-security-test:4.0.1.RELEASE’
}
task wrapper(type: Wrapper) {
gradleVersion = ‘2.3’
}
После чего в консольке в той же директории где build.gradle пишем
gradle wrapper ./gradlew build (или для windows ./gradlew.bat build)
Теперь можно использвать gradlew.bat/gradlew в зависимости от ОС.
1.3.1 Для остальных
- Заходите через консоль в папку где находятся ваши проекты Idea
- git clone github.com/MaxPovver/ForHabrahabr.git
- git cd ForHabrahabr/
- git checkout quikstart
- Все, теперь у вас есть готовая структура проекта 🙂
1.4 База данных
В качестве БД выберем MySQL как самую простую для quickstart. Создаем ее на localhost,
в ней создаем базу forhabrahabr, в дальнейшем в ней будем создавать таблички
users
roles
users_roles
posts
likes
Но об этом позже, пока достаточно создать БД.
2. Начинаем кодить
2.1 Создание проекта
Итак, для начала откроем наш только что созданный проект в Intellj IDEA, она увидит Gradle и предложит использовать его:
(Welcome to ItelliJ IDEA -> Open -> ForHabrahabr)
В этом окошке просто жмете ок, если его нет(или проблемы с Gradle JVM) — пишите в лс, буду разбираться что не так.
В итоге должен получиться такой проект:
2.2 Добавляем первый код
Первым делом создадим пакет для всех классов, назовем его habraspring(обычная папка в src/main/java/), а в нем — первый
класс Application
package habraspring; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication @ComponentScan @EnableJpaRepositories(basePackages = {"habraspring"}) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
Но в таком виде наше приложение еще не запустится, надо показать автоконфигуратору где находится база данных, для этого добавим файл в папку resources/ файл
application.properties
#settings for database spring.datasource.url=jdbc:mysql://localhost/forhabrahabr spring.datasource.username=root spring.datasource.password= spring.datasource.driver-class-name=com.mysql.jdbc.Driver #turned on to enable lazy loading spring.jpa.properties.hibernate.enable_lazy_load_no_trans = true
Также надо создать в resources/ папку templates/ для шаблонизатора.
Папка ресурсов будет выглядеть вот так
Не обращайте внимание на файлы .gitkeep, для работы программы они не нужны, можно их спокойно удалять/не создавать.
Готово, можете впервые запустить ваше приложение без падения 🙂
Для запуска нужно запустить таску bootRun(двойной клик по ней)
Если нет такой панельки, идем в View -> Tool Windows -> Gradle
В логе приложения будет что-то вроде такого:
15:24:47: Executing external task 'bootRun'... :compileJava UP-TO-DATE :processResources :classes :findMainClass :bootRun . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v1.2.5.RELEASE) 2015-07-11 14:24:49.180 INFO 12590 --- [ main] habraspring.Application : Starting Application on MacBook-Pro-Maksim.local with PID 12590 (/Users/admin/IdeaProjects/ForHabrahabr/build/classes/main started by admin in /Users/admin/IdeaProjects/ForHabrahabr) 2015-07-11 14:24:49.230 INFO 12590 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2eda0940: startup date [Sat Jul 11 14:24:49 MSK 2015]; root of context hierarchy 2015-07-11 14:24:50.029 INFO 12590 --- [ main] o.s.b.f.s.DefaultListableBeanFactory : Overriding bean definition for bean 'beanNameViewResolver': replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter; factoryMethodName=beanNameViewResolver; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]] 2015-07-11 14:24:50.701 INFO 12590 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [class org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$1f1e9ae] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2015-07-11 14:24:50.727 INFO 12590 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'transactionAttributeSource' of type [class org.springframework.transaction.annotation.AnnotationTransactionAttributeSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2015-07-11 14:24:50.741 INFO 12590 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'transactionInterceptor' of type [class org.springframework.transaction.interceptor.TransactionInterceptor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2015-07-11 14:24:50.746 INFO 12590 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.config.internalTransactionAdvisor' of type [class org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2015-07-11 14:24:51.168 INFO 12590 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http) 2015-07-11 14:24:51.408 INFO 12590 --- [ main] o.apache.catalina.core.StandardService : Starting service Tomcat 2015-07-11 14:24:51.409 INFO 12590 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet Engine: Apache Tomcat/8.0.23 2015-07-11 14:24:51.601 INFO 12590 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2015-07-11 14:24:51.601 INFO 12590 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 2374 ms 2015-07-11 14:24:52.570 INFO 12590 --- [ost-startStop-1] b.a.s.AuthenticationManagerConfiguration : Using default security password: bd1659e1-4c49-43a2-9fd6-2ca7d46e9e23 2015-07-11 14:24:52.614 INFO 12590 --- [ost-startStop-1] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/css/**'], [] 2015-07-11 14:24:52.614 INFO 12590 --- [ost-startStop-1] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/js/**'], [] 2015-07-11 14:24:52.614 INFO 12590 --- [ost-startStop-1] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/images/**'], [] 2015-07-11 14:24:52.614 INFO 12590 --- [ost-startStop-1] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/**/favicon.ico'], [] 2015-07-11 14:24:52.614 INFO 12590 --- [ost-startStop-1] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: Ant [pattern='/error'], [] 2015-07-11 14:24:52.650 INFO 12590 --- [ost-startStop-1] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/**']]], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@5854c7d0, org.springframework.security.web.context.SecurityContextPersistenceFilter@874f491, org.springframework.security.web.header.HeaderWriterFilter@34c74c36, org.springframework.security.web.authentication.logout.LogoutFilter@609329b3, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@a37632c, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@33a36df4, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@a3153e3, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@1b8b1dc9, org.springframework.security.web.session.SessionManagementFilter@5ad0989a, org.springframework.security.web.access.ExceptionTranslationFilter@3e313564, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@1fb86c05] 2015-07-11 14:24:52.723 INFO 12590 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'characterEncodingFilter' to: [/*] 2015-07-11 14:24:52.724 INFO 12590 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*] 2015-07-11 14:24:52.724 INFO 12590 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'springSecurityFilterChain' to: [/*] 2015-07-11 14:24:52.724 INFO 12590 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/] 2015-07-11 14:24:53.410 INFO 12590 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default' 2015-07-11 14:24:53.425 INFO 12590 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [ name: default ...] 2015-07-11 14:24:53.500 INFO 12590 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {4.3.10.Final} 2015-07-11 14:24:53.503 INFO 12590 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found 2015-07-11 14:24:53.505 INFO 12590 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist 2015-07-11 14:24:53.628 INFO 12590 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {4.0.5.Final} 2015-07-11 14:24:53.711 INFO 12590 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect 2015-07-11 14:24:53.774 INFO 12590 --- [ main] o.h.h.i.ast.ASTQueryTranslatorFactory : HHH000397: Using ASTQueryTranslatorFactory 2015-07-11 14:24:54.244 INFO 12590 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@2eda0940: startup date [Sat Jul 11 14:24:49 MSK 2015]; root of context hierarchy 2015-07-11 14:24:54.328 INFO 12590 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest) 2015-07-11 14:24:54.328 INFO 12590 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest) 2015-07-11 14:24:54.356 INFO 12590 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2015-07-11 14:24:54.357 INFO 12590 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2015-07-11 14:24:54.393 INFO 12590 --- [ main] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] 2015-07-11 14:24:54.723 INFO 12590 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup 2015-07-11 14:24:54.800 INFO 12590 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 2015-07-11 14:24:54.803 INFO 12590 --- [ main] habraspring.Application : Started Application in 5.945 seconds (JVM running for 6.529)
Попробуйте теперь зайти по адресу http://localhost:8080, должен работать 🙂
Ну а теперь хотелось бы увидеть немного контента, не так ли?)
2.3 Контент
Для этого нам понадобится создать два класса конфигурации(помните, никаких XML!) во вложенной папке config, а также добавить home.html (аналог index.html) в папку resources.
Файлы конфигурации у нас простейшие, ведь мы их используем для страниц без контроллера:
package habraspring.config; 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"); } }
package habraspring.config; import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 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 @EnableGlobalMethodSecurity(prePostEnabled = true) @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/home").permitAll(); } }
Ну и простейшая домашняя страничка:
<!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>Habrahabr</title> </head> <body> <h1>Welcome!</h1> <p>Yours home page.</p> </body> </html>
Как должен выглядеть проект на этом этапе можно посмотреть(и скачать) тут:
github.com/MaxPovver/ForHabrahabr/tree/withbasicmvc
Если на данный момент все сделано правильно, по http://localhost:8080 у вас должно выводится
Welcome! Yours home page.
3. Добавляем работу с БД
Итак, мы хотим добавить контроллеров, и чтобы доступ к ним выдавался только авторизованным юзерам, но у нас их пока нет 🙂
Для того, чтобы механизм авторизации заработал, нам надо добавить сущность юзера в проект.
Необходимые шаги:
- Добавить класс, описывающий сущность юзера в бд
- Добавить репозиторий новой сущности
- Добавить «связь» между механизмом Spring Security и нашей сущностью
- Все везде зарегистрировать
- «Включить» Spring Security
3.1 Сущность «User»
Сначала создадим в бд простейшую табличку users с полями id, username, password.
Теперь создадим подпакет entities для сущностей и создадим в нем класс User:
package habraspring.entities; import javax.persistence.*; @Entity @Table(name="users") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String username; private String password; public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } protected User(){} public User(String name, String pass) { username = name; password = pass; } }
Никаких hbm.xml не нужно, даже аннотировать поля не нужно(исключение — поле ID, его всегда надо отмечать)
3.2 Репозиторий UsersRepository
Здесь Spring все делает за нас, достаточно отнаследоваться чтобы он понял что ему генерировать, код же писать не нужно вообще:
package habraspring.repositories; import habraspring.entities.User; import org.springframework.data.repository.CrudRepository; public interface UsersRepository extends CrudRepository<User, Long> { User findByUsername(String username); }
3.3 Добавление связи между юзером и Spring Security
Для этого нам надо создать класс реализующий интерфейс UserDetailsService и подлючить его в WebSecurityConfig
package habraspring.utils; import habraspring.entities.User; import habraspring.repositories.UsersRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.InternalAuthenticationServiceException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collection; import java.util.List; @Service public class MySQLUserDetailsService implements UserDetailsService { @Autowired UsersRepository users; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { UserDetails loadedUser; try { User client = users.findByUsername(username); loadedUser = new org.springframework.security.core.userdetails.User( client.getUsername(), client.getPassword(), DummyAuthority.getAuth()); } catch (Exception repositoryProblem) { throw new InternalAuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem); } return loadedUser; } static class DummyAuthority implements GrantedAuthority { static Collection<GrantedAuthority> getAuth() { List<GrantedAuthority> res = new ArrayList<>(1); res.add(new DummyAuthority()); return res; } @Override public String getAuthority() { return "USER"; } } }
Теперь изменим код WebSecurityConfig:
package habraspring.config; import habraspring.utils.MySQLUserDetailsService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 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 @EnableGlobalMethodSecurity(prePostEnabled = true) @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/home").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .permitAll(); } @Autowired private MySQLUserDetailsService mySQLUserDetailsService; @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(mySQLUserDetailsService); } }
Добавим страничку входа login.html и «секретную»(только для авторизованных) страничку secret.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>Secret page</title> </head> <body> <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1> <form th:action="@{/logout}" method="post"> <input type="submit" value="Sign Out"/> </form> </body> </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>Login page</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>
И сделаем новые странички доступными без контроллера, добавив в WebMvcConfig 2 строчки:
registry.addViewController("/login").setViewName("login"); registry.addViewController("/secret").setViewName("secret");
Готово! Теперь по адресу http://localhost:8080 у вас должно все выводиться нормально,
а вот по адресу localhost:8080/secret Вы пройти не сможете — будет кидать в /login, требуя валидную пару юзер/пароль.
Теперь добавьте в Вашу таблицу forhabrahabr.users запись c паролем и логином user, user (или запустите скрипт github.com/MaxPovver/ForHabrahabr/blob/withauth/import_me.sql в вашей дб).
Если вы все сделали правильно, теперь Вас должно пускать в /secret =)
4. К чему мы пришли
Итак, мы уже используем полноценное Spring MVC приложение с использованием Spring Security для безопасности и Spring JPA для работы с БД. И никаких XML =)
4.1 Для желающих запустить готовый проект
- git clone github.com/MaxPovver/ForHabrahabr.git
- cd ForHabrahabr/
- git checkout withauth
- запускаем в своей локальной mysql бд import_me.sql(или создаем руками табличку и данные для нее)
-
Открываем через IDEA созданную папку ForHabrahabr
-
Нету панельки Gradle? Открываем ее тут
-
Запускаем bootRun
- На этом шаге уже должно все работать
Многое пришлось опустить/не объяснять чтобы не запутать окончательно, но если считаете необходимым добавить что-то уже сейчас — пишите в лс.
Осталось материала еще минимум на одну часть, если, конечно, тема актуальна. (Controllers, EntityToEntity(ManyToOne OneToOne etc), User Roles etc)
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
ссылка на оригинал статьи http://habrahabr.ru/post/262323/
Добавить комментарий