#mysql #spring-boot #spring-security #spring-jdbc #spring-session
#mysql #весенняя загрузка #весна-безопасность #spring-jdbc #весенняя сессия
Вопрос:
Я использую весеннюю сессию с JDBC и Mysql. Вход в систему Spring Security выполнен успешно, но имя принципала равно нулю.
У кого-нибудь есть идея, в чем ошибка?
Файлы:
application.yaml:
session:
store-type: jdbc
jdbc:
initialize-schema: always
table-name: SPRING_SESSION
Конфигурация:
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@EnableJdbcHttpSession
@EnableJpaRepositories(basePackageClasses = UsersRepository.class)
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/*").authenticated().anyRequest().permitAll()
.antMatchers("/sources/*").anonymous().anyRequest().permitAll()
.antMatchers("/public/*").anonymous().anyRequest().permitAll()
.and()
.formLogin().
loginPage("/login").
loginProcessingUrl("/app-login").
usernameParameter("app_username").
passwordParameter("app_password").
permitAll()
.and()
.exceptionHandling().
accessDeniedPage("/error403");
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Вот изображение таблицы базы данных:
Ссылка
The 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>sandbox</groupId>
<artifactId>TestApp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
</project>
ОБНОВЛЕНИЕ 18.03.19
Я не могу изменить стратегию безопасности. Ссылка
Обновить
Если я добавлю следующий компонент в свою конфигурацию безопасности, principal_name в базе данных больше не будет иметь значения null. Теперь есть имя пользователя, вошедшего в систему. НО после каждой перезагрузки сайта создается новая сессия, поэтому пользователь не может сказать, что вошел в систему.
@Bean
public HttpSessionIdResolver httpSessionIdResolver(){
return new HeaderHttpSessionIdResolver("X-Auth-Token");
}
Комментарии:
1. добавить pom.xml коды
2. Вставьте свой код UserDetailsService в вопрос
3. Почему вы работаете с Spring Boot (судя по добавлению всех
@Enable*
аннотаций. Также где код, который вы используете для печати этой строки (то есть физически в вашем коде).4. Пожалуйста, ознакомьтесь с обновлением..
Ответ №1:
Я, наконец, нашел проблему. Мне пришлось реализовать интерфейс, сериализуемый для моего пользовательского класса. Теперь все работает нормально.
Ответ №2:
Ваши учетные данные удаляются после входа в систему. Вы можете предотвратить это, но пароль вы не найдете из Principle
или SecurityContext
. Попробуйте приведенный ниже код в приведенном выше файле конфигурации:
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.eraseCredentials(false);
auth.userDetailsService(myUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
Обновить
Добавьте следующий компонент и посмотрите результат:
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
Также, пожалуйста, добавьте pom.xml содержание вашего вопроса.
Обновить
Добавьте эти строки в свой pom, если вы используете Thymeleaf:
<properties>
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version>
<thymeleaf-extras-springsecurity4.version>3.0.4.RELEASE</thymeleaf-extras-springsecurity4.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
Теперь основная часть, файл конфигурации:
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@EnableJdbcHttpSession
@EnableJpaRepositories(basePackageClasses = UsersRepository.class)
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
<strike>@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}</strike>
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.eraseCredentials(false);
auth.userDetailsService(myUserDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/*").authenticated().anyRequest().permitAll()
.antMatchers("/sources/*").anonymous().anyRequest().permitAll()
.antMatchers("/public/*").anonymous().anyRequest().permitAll()
.and()
.formLogin().
loginPage("/login").
loginProcessingUrl("/app-login").
usernameParameter("app_username").
passwordParameter("app_password").
permitAll()
.and()
.exceptionHandling().
accessDeniedPage("/error403");
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Наконец, контроллер:
@ResponseBody
@GetMapping("/check")
public String check(Principal principal) {
System.out.println(principal.getName());
return "ok";
}
Комментарии:
1. Я пробовал это, но безуспешно. У вас есть какие-либо другие идеи?
2. @Tom вы можете принять правку к вашему вопросу и добавить обновленные коды.
3. К сожалению, ваш обновленный ответ ничего не изменил. 🙁
4. @Tom проверьте обновленный ответ. удалите часть strike из вашего конфигурационного файла
5. Я заменил свою конфигурацию вашим ответом и удалил забастовку. Но безуспешно :/
Ответ №3:
Если вы используете spring 3, то это может помочь вам получить имя пользователя
@RequestMapping(value="", method = RequestMethod.method)
public String showCurrentUser(Principal principal) {
return principal.getName();
}
Или изменение SecurityContextHolder MODE
может помочь вам. Смотрите здесь
@GetMapping(value = {"/", ""})
public String start(Principal principal, Model model) {
if(principal.getName()!=null)
{
//your code
}
else
{
//your code
}
return something;
}
Комментарии:
1.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); System.out.println(principal);
Вывод:User{id=0, email='null', password='null', firstName='null', lastName='null', active=false, roles=null}
2. Как я могу изменить режим SecurityContextHolder?
3. @Tom SecurityContextHolder.YOUR_MODE изменит режим. обновленный ответ вам не помогает?
4. Я пытаюсь это протестировать. Но куда я должен вставить эти строки? Какой файл? Контроллер, на котором я хочу отобразить принципал?
5. @Tom Да, вы можете использовать это в контроллере, обратитесь к обновленному ответу