Error: отношение "persistent_logins" не существует

 
 
 
Сообщения:66
@Configuration
@ComponentScan("ru.task")
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Qualifier(value = "userDetailsServiceImpl")
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Qualifier("dataSource")
    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                .antMatchers("/users/**").hasAuthority("ADMIN")
                .antMatchers("/signUp/**").permitAll()
                .antMatchers("/").authenticated()
                .antMatchers("/css/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .usernameParameter("login")
                .defaultSuccessUrl("/")
                .loginPage("/login")
                .permitAll()
                .and()
                .logout()
                .and()
                .rememberMe()
                .rememberMeParameter("remember-me")
                .tokenRepository(tokenRepository());

        http.csrf().disable();
    }

    @Bean
    public PersistentTokenRepository tokenRepository() {

        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);

        return tokenRepository;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        DaoAuthenticationConfigurer<AuthenticationManagerBuilder, UserDetailsService> authenticationConfigurer =
                auth.userDetailsService(this.userDetailsService);

        authenticationConfigurer.passwordEncoder(this.passwordEncoder);
    }

}




Quote:
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [delete from persistent_logins where username = ?]; nested exception is org.postgresql.util.PSQLException: ОШИБКА: отношение "persistent_logins" не существует
Позиция: 13



При попытке выхода из системы, то есть переход на адрес /logout, появляется ошибка.

Что это такое и как это исправить ?
 
 
Сообщения:9831
persistent_logins - это таблица в которой Spring Security сохраняет данные для механизма Remember Me. Т.к. он у тебя активирован, то Spring Security пытается с этой таблицей работать. Ее нужно создать, либо у самого SS есть какие-то средства, либо можно найти нужный DDL и добавить миграцию к себе в проект.
 
 
Сообщения:66
я создал таблицу, ошибка исчезла, но механизм remember-me не работает почему то, так как таблица не заполняется

#Для хранения маркеров безопасности для клиентов, которые прошли аутентификацию
# и активировали опцию remember-me
create table logins_persistent(
  username varchar(50) not null,
  series varchar(64) primary key,
  token varchar(64) not null,
  last_used timestamp not null
);


кроме того, на использовании hiberante без использования Spring Data, у меня вот такой код

сущность
package com.boraji.tutorial.spring.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
import java.util.Objects;

@Entity
@Table(name = "LOGINS_PERSISTENT")
public class PersistentLogin {

    @Id
    @Column(name = "SERIES")
    private String series;

    @Column(name = "USERNAME", nullable = false)
    private String username;

    @Column(name = "TOKEN", nullable = false)
    private String token;

    @Column(name = "LAST_USED", nullable = false)
    private Date lastUsed;

    public String getSeries() {
        return series;
    }

    public void setSeries(String series) {
        this.series = series;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public Date getLastUsed() {
        return lastUsed;
    }

    public void setLastUsed(Date lastUsed) {
        this.lastUsed = lastUsed;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        PersistentLogin that = (PersistentLogin) o;
        return Objects.equals(series, that.series) &&
                Objects.equals(username, that.username) &&
                Objects.equals(token, that.token) &&
                Objects.equals(lastUsed, that.lastUsed);
    }

    @Override
    public int hashCode() {
        return Objects.hash(series, username, token, lastUsed);
    }

    @Override
    public String toString() {
        return "PersistentLogin{" +
                "series='" + series + '\'' +
                ", username='" + username + '\'' +
                ", token='" + token + '\'' +
                ", lastUsed=" + lastUsed +
                '}';
    }
}


реализация PersistentTokenRepository

package com.boraji.tutorial.spring.dao;

import com.boraji.tutorial.spring.model.PersistentLogin;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.stereotype.Repository;

import javax.transaction.Transactional;
import java.util.Date;

@Repository("persistentTokenRepository")
@Transactional
public class PersistentTokenDaoImp implements PersistentTokenRepository {

    private final SessionFactory sessionFactory;

    @Autowired
    public PersistentTokenDaoImp(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    /*создание нового маркера безопасности
    * `PersistentRememberMeToken token` - передает детали пользователя, который
    * прошел аутентификацию*/
    @Override
    public void createNewToken(PersistentRememberMeToken token) {

        PersistentLogin logins = new PersistentLogin();

        logins.setUsername(token.getUsername());
        logins.setSeries(token.getSeries());
        logins.setToken(token.getTokenValue());
        logins.setLastUsed(token.getDate());

        sessionFactory.getCurrentSession().save(logins);

    }

    /*обновление текущего маркера безопансности*/
    @Override
    public void updateToken(String series, String tokenValue, Date lastUsed) {

        Session session = sessionFactory.getCurrentSession();
        PersistentLogin logins = session.get(PersistentLogin.class, series);

        logins.setToken(tokenValue);
        logins.setLastUsed(lastUsed);

    }


    @Override
    public PersistentRememberMeToken getTokenForSeries(String seriesId) {

        Session currentSession = sessionFactory.getCurrentSession();

        PersistentLogin login = currentSession.get(PersistentLogin.class, seriesId);

        if (login != null) {

            PersistentRememberMeToken persistentRememberMeToken =
                    new PersistentRememberMeToken(
                            login.getUsername(),
                            login.getSeries(),
                            login.getToken(),
                            login.getLastUsed()
                    );

            return persistentRememberMeToken;
        }

        return null;
    }

    /*удаление маркера безопасности, после удаления пользователя из сессии*/
    @Override
    public void removeUserTokens(String username) {

        String jpqlQuery = "delete from PersistentLogin where username=:userName";

        Session currentSession = sessionFactory.getCurrentSession();

        Query query = currentSession.createQuery(jpqlQuery);

        Query userByName = query.setParameter("userName", username);

        userByName.executeUpdate();

    }
}


Здесь используется
private final SessionFactory sessionFactory;


Вот в таком случае все работает.

А когда используется Spirng Data , как быть ?

А нужны ли эти классы при использовании spring data ?

Я пока не нашел примеров и статей, кроме вот этих

первый и второй
Изменен:19 мая 2019 15:33
 
 
Сообщения:66
Для Srpitg Boot нужно только создать таблицу

CREATE TABLE IF NOT EXISTS persistent_logins (
  username  VARCHAR(64) NOT NULL,
  series    VARCHAR(64) NOT NULL,
  token     VARCHAR(64) NOT NULL,
  last_used TIMESTAMP   NOT NULL,
  PRIMARY KEY (series)
);


Этого будет достаточно, больше не нужно ничего настраивать.

Для Spring vanilla + JPA, не знаю нужно ли что добавлять.
 
Модераторы:wedens
Сейчас эту тему просматривают:Нет