Я создал небольшое приложение для изучения веб-безопасности при загрузке спринта. Пример приложения в основном основан на частичных инструкциях, приведенных в книге «Spring Boot in Action».
Проблема, с которой я сталкиваюсь, заключается в том, что, несмотря на настройку доступа, как показано ниже, при открытии http://localhost: 8080 / reader / ishwar приложение не может перейти на страницу входа. Сразу открывается страница, представленная http://localhost: 8080 / reader / ishwar . Насколько я понял безопасность пружины, если применяется .access (""), то для проверки доступа по умолчанию пружина должна перенаправить пользователя на страницу входа. Но это не так.
package com.example.readingList;
import org.springframework.beans.factory.annotation.Autowired;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ReaderRepository readerRepository;
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.
authorizeRequests()
.antMatchers("/readers").access("hasRole('READER')")
.antMatchers("/login").permitAll()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.failureUrl("/login?error=true");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return readerRepository.getOne(username);
}
});
}
}
НО , если я изменю код на ниже, то при просмотре http://localhost: 8080 / reader / ishwar я перенаправлюсь на страница авторизации. Что не так в первой конструкции? Я имею в виду, почему .access ("") не работает
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ReaderRepository readerRepository;
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.
authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.failureUrl("/login?error=true");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return readerRepository.getOne(username);
}
});
}
}
Ниже показано, как написано ReaderRepository
package com.example.readingList;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ReaderRepository extends JpaRepository<Reader, String> {
}
Ниже представлен класс Reader. Я намеренно предоставил роль «ПИСАТЕЛЬ», так как хочу видеть, что попытка доступа к странице должна завершиться неудачей, так как отсутствует разрешение READER. Но как таковой, даже если я включаю разрешение «ЧИТАТЕЛЬ», в поведении нет никаких изменений.
package com.example.readingList;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Arrays;
import java.util.Collection;
@Entity
public class Reader implements UserDetails {
private static final long serialVersionUID = 1L;
@Id
private String username;
private String password;
private String fullname;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return Arrays.asList(new SimpleGrantedAuthority("WRITER"));
}
//@Override
public String getPassword() {
return password;
}
public void setPassword(String password)
{
this.password = password;
}
//@Override
public String getUsername() {
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getFullname()
{
return fullname;
}
public void setFullname(String fullname)
{
this.fullname = fullname;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
Пожалуйста, обратите внимание, что я не реализовал источник данных для хранения / извлечения пользователя и пароля. Я ожидал увидеть по крайней мере перенаправление на http://localhost: 8080 / login первым, но не произойдет, если я использую первую конструкцию.
Ниже мой pom. xml file
https://maven.apache.org/xsd/maven-4.0.0.xsd "> 4.0.0
<groupId>com.example</groupId>
<artifactId>readingList</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>readingList</name>
<description>Reading List project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Класс ReadingListApplication
@Configuration
@SpringBootApplication
public class ReadingListApplication implements WebMvcConfigurer
{
public static void main(String[] args) {
SpringApplication.run(ReadingListApplication.class, args);
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
Класс ReadingListController
package com.example.readingList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
@Controller
public class ReadingListController {
private ReadingListRepository readingListRepository;
@Autowired
public ReadingListController(ReadingListRepository readingListRepository)
{
this.readingListRepository = readingListRepository;
}
@RequestMapping(value="/readers/{reader}", method= RequestMethod.GET)
public String readersBook(@PathVariable("reader") String reader, Model model)
{
List<Book> readingList = readingListRepository.findByReader(reader);
if (readingList.isEmpty() == false) {
model.addAttribute("books", readingList);
}
return "readingList";
}
@RequestMapping(value="/readers/{reader}", method= RequestMethod.POST)
public String addToReadingList(@PathVariable("reader") String reader, Book book)
{
book.setReader(reader);
readingListRepository.save(book);
return "redirect:/readers/{reader}";
}
}