LINUX.ORG.RU

Почему не авторизует в Spring Security + Hibernate?

 , , ,


0

2

Весь гугл и доки ведут к одному и тому же варианту настроек.

У меня вот что.

security-context.xml:

<http use-expressions="true" auto-config="true">
        <csrf disabled="true"/>
        
        <intercept-url pattern="/resources/**" access="permitAll" />
        <intercept-url pattern="/welcome*" access="permitAll" />
        <intercept-url pattern="/login*" access="isAnonymous()" />
        <intercept-url pattern="/user*" access="permitAll" />
        <intercept-url pattern="/register*" access="isAnonymous()" />
        <intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
        <form-login login-page="/login"
                    login-processing-url="/j_spring_security_check"
                    authentication-failure-url="/login?error"
                    default-target-url="/welcome" 
                    username-parameter="j_username"
                    password-parameter="j_password"
                    />
        <logout logout-url="/login?logout" logout-success-url="/welcome"/>
    </http>
    
    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="userDAO" >
            
        </authentication-provider>
    </authentication-manager>

login.jspx:

<c:url value='/j_spring_security_check' var="springSecurityUrl" />
    
    <div class="generic-container container">
        <div class="panel panel-default">
            <div class="panel-heading"><span class="lead">${loginForm}</span></div>

            <div class="formcontainer">
                <form action="${springSecurityUrl}" name="userForm" class="form-horizontal" method="POST">
                    <!-- <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> -->
                    
                    <input type="hidden" />

                    <div class="row">
                        <div class="form-group col-md-10">
                            <jsp:text/>
                        </div>
                    </div>

                    <div class="row">
                        <div class="form-group col-md-10">
                            <label class="col-md-2 control-label" for="login">${login}</label>
                            <div class="col-md-7">
                                <input type="text" name="j_username" id="login"
                                       class="username form-control input-sm" 
                                       placeholder="Enter your login" required=""/>
                            </div>
                        </div>
                    </div>

                    <div class="row">
                        <div class="form-group col-md-10">
                            <label class="col-md-2 control-label" for="j_password">${password}</label>
                            <div class="col-md-7">
                                <input type="text" name="j_password" id="password"
                                       class="form-control input-sm" 
                                       placeholder="Enter your Password"/>
                            </div>
                        </div>
                    </div>
                           
                    <div class="row">
                        <div class="col-md-10">
                            <span class="col-md-2"><jsp:text/></span>
                            <span class="col-md-1">
                                <button type="submit" class="btn btn-primary btn-sm">Login</button>
                            </span>
                            <div class="form-actions floatRight col-md-7">
                            </div>
                        </div>
                    </div>
                </form>
            </div>
        </div>
    </div>

UserDAOImpl.java:

@Repository("userDAO")
@Transactional
public class UserDAOImpl implements UserDAO, UserDetailsService {

    public static enum AUTHORITY {
        ROLE_USER("ROLE_USER"),
        ROLE_ADMIN("ROLE_ADMIN"),
        ROLE_GUEST("ROLE_GUEST")
        ;
        private final String value;
        AUTHORITY(String a) {
            value = a;
        }
        @Override
        public String toString() {
            return value;
        }
    }
    
    private Logger log = LoggerFactory.getLogger(UserDAOImpl.class);
    
    @Autowired
    private SessionFactory sessionFactory;
    
    @Resource(name="sessionFactory")
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
    
    private Session session() {
        return sessionFactory.getCurrentSession();
    }
    
    @Override
    public User load(long id) {
        log.debug("Loading user with ID: "+id);
        return (User) session().get(User.class, id);
    }

    @Override
    public User create() {
        log.debug("Creating new user");
        return new User();
    }

    @Override
    public boolean save(User user) {
        log.debug("Saving user with ID: "+user.getId()+", login: "+user.getLogin());
        session().save(user);
        return true;
    }

    @Override
    public Authority createAuthority(User user) {
        log.debug("Creating new authority for User: "+user);
        Authority authority = new Authority();
        authority.setUser(user);
        return authority;
    }
    

    @Override
    public UserDetails loadUserByUsername(String login) throws UsernameNotFoundException {
        log.debug("Loading user by login: "+login);

        Query query = session().createSQLQuery("SELECT user_id FROM finansist.users WHERE login = :login");
        query.setString("login", login);
        try {
            long id = -1;
            Object oid = query.uniqueResult();
            if (oid instanceof BigInteger) {
                id = ((BigInteger) oid).longValue();
                return this.load(id);
            } else {
                throw new UsernameNotFoundException("Not found");
            }
        } catch (NullPointerException e) {
            throw new UsernameNotFoundException("Not found");
        }
    }
    
}

смотрю отладчиком в UserDAOImpl.loadUserByUsername(...), параметр передается верный - логин. Проходит до возврата экземпляра User (это Entity, implemented UserDetails) через return this.load(id), но дальше в браузере делается редирект на /login?error, как будто авторизация фэйлится.

Что я не так сделал? Может, мне стоит еще создать свои бины-реализации AuthenticationManager и AuthenticationProvider? Что еще не хватает?

Ошибок в консоль не выводится, т.е., как я понимаю, Spring Security не валится нигде.

★★★★★

да фиг это на форуме отдебажишь :)

может у юзверя не устанавливается роль из списка? Нету роли - нету логина

не пробовал нагуглить готовый сниппет? например

https://github.com/fycth/spring-security-hibernate-auth-example

stevejobs ★★★☆☆ ()
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от stevejobs

нет, роли есть, хранятся в виде HashSet, отдаются согласно интерфейсу UserDetails.

Смотрю на этот пример и в упор не вижу различий от всех этих нагугленных мной в интернете. Только мое - не работает.

bvn13 ★★★★★ ()

Ну, как я и предположил. Создал реализацию AuthenticationProvider и все заработало.

@Component(value = "authenticationProviderImpl")
public class AuthenticationProviderImpl implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userService;
    
    //@Resource(name="userService")
    public void setUserService(UserDetailsService userService) {
        this.userService = userService;
    }
    
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String login = authentication.getName();
        String password = authentication.getCredentials().toString();
 
        if (userService == null)
            throw new InternalAuthenticationServiceException("UserService is null");
        
        UserDetails user = userService.loadUserByUsername(login);
        if (user == null)
            throw new AuthenticationCredentialsNotFoundException("Not found");
        
        if (user.getPassword().equals(password)) {
            return new UsernamePasswordAuthenticationToken(user, authentication.getCredentials(), user.getAuthorities());
        } else {
            throw new AuthenticationServiceException("Unable to auth against third party systems");
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
    
}
bvn13 ★★★★★ ()
Ответ на: комментарий от stevejobs

Мне не понятно, почему все туторы и маны в инете пишут, что достаточно просто создать настройку, а мне приходится реализовывать бины для UserDetailsService, AuthenticationProvider? И ведь оно не ругается, что их создавать необходимо. А просто - редирект на форму с ошибкой. И как понять, что именно не хватает?

Вопросы, скорее всего, риторические.

bvn13 ★★★★★ ()
Ответ на: комментарий от bvn13

а версия спринга и спрингсекурити такая же как в туториалах?

я вот тоже сейчас разбираюсь с самыми свежими версиями (из мастера, если точнее), все совсем по-другому

stevejobs ★★★☆☆ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.