Рубрики
Без рубрики

Весенняя Безопасность Запомни Мой Пример

– Весенняя Безопасность Запомни Мой Пример

Автор оригинала: mkyong.

В этом уроке мы покажем вам, как реализовать функцию входа “Запомнить меня” в Spring Security, что означает, что система запомнит пользователя и выполнит автоматический вход в систему даже после истечения срока действия сеанса пользователя.

Используемые технологии и инструменты:

  1. Пружина 3.2.8. ОСВОБОЖДЕНИЕ
  2. Защита пружины 3.2.3.ОСВОБОЖДЕНИЕ
  3. Весенний JDBC 3.2.3.ВЫПУСК
  4. Затмение 4.2
  5. JDK 1.6
  6. Мавен 3
  7. Сервер MySQL 5.6
  8. Кот 6 и 7 (сервлет 3.x)
  9. Тест с помощью Google Chrome

Несколько кратких заметок:

  1. В Spring Security существует два подхода к реализации “запомни меня” – Простой токен на основе хэша и постоянный подход к токенам.
  2. Чтобы понять, как работает “запомнить меня”, пожалуйста, прочтите эти статьи – Ссылка на Spring remember me , Лучшая практика использования файлов cookie для постоянного входа , Улучшена Лучшая практика Использования Файлов Cookie Для Постоянного Входа .
  3. В этом примере используется “Подход с сохраняемым токеном”, см. Spring PersistentTokenBasedRememberMeServices .
  4. В этом примере используется аутентификация MySQL и базы данных (через Spring JDBC).
  5. Будет создана таблица “Постоянные логины” для хранения маркера входа и серии.

Рабочие процессы проекта:

  1. Если пользователь войдет в систему с отметкой “запомнить меня”, система сохранит файл cookie “запомнить меня” в запрошенном браузере.
  2. Если браузер пользователя предоставляет действительный файл cookie “запомнить меня”, система выполнит автоматический вход в систему.
  3. Если пользователь входит в систему с помощью файлов cookie “запомнить меня”, для обновления сведений о пользователе пользователю необходимо снова ввести имя пользователя и пароль (рекомендуется избегать кражи файлов cookie для обновления информации о пользователе.

P.S Это очень высокий уровень того, как должно работать “запомни меня”, для получения подробной информации, пожалуйста, обратитесь к приведенным выше ссылкам в “кратких заметках”.

1. Демонстрация проекта

2. Каталог проектов

Просмотрите структуру каталогов проекта.

3. Сценарии MySQL

Сценарии SQL для создания пользователей , роли_пользователя и постоянные логины .

CREATE  TABLE users (
  username VARCHAR(45) NOT NULL ,
  password VARCHAR(45) NOT NULL ,
  enabled TINYINT NOT NULL DEFAULT 1 ,
  PRIMARY KEY (username));

CREATE TABLE user_roles (
  user_role_id int(11) NOT NULL AUTO_INCREMENT,
  username varchar(45) NOT NULL,
  role varchar(45) NOT NULL,
  PRIMARY KEY (user_role_id),
  UNIQUE KEY uni_username_role (role,username),
  KEY fk_username_idx (username),
  CONSTRAINT fk_username FOREIGN KEY (username) REFERENCES users (username));

INSERT INTO users(username,password,enabled)
VALUES ('mkyong','123456', true);

INSERT INTO user_roles (username, role)
VALUES ('mkyong', 'ROLE_USER');
INSERT INTO user_roles (username, role)
VALUES ('mkyong', 'ROLE_ADMIN');

CREATE TABLE 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)
);

4. Запомни меня (пример XML)

Чтобы включить “запомнить меня” в конфигурации XML, поместите тег remember-me в http следующим образом:

  
  
    

    

    
    

    
    

  
  

	
	
	
	
  

   
  
  
	
  
  1. срок действия токена – секунды – Дата истечения срока действия файла cookie “запомни меня” в секундах. Например, недели (14 дней), день, часы.
  2. параметр “запомни меня” – Название “флажка”. По умолчанию используется значение “_spring_security_remember_me”.
  3. источник данных-ссылка – Если это указано, будет использоваться “Постоянный подход к маркерам”. По умолчанию используется “Простой подход к токенам на основе хэша”.

5. Запомни меня (Пример аннотации)

Эквивалент аннотаций:

package com.mkyong.config;

import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	DataSource dataSource;
	//...
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {

	  http.authorizeRequests()
	      .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
	    .and()
	      .formLogin()
	        .successHandler(savedRequestAwareAuthenticationSuccessHandler())
		.loginPage("/login")
	        .failureUrl("/login?error")
		.loginProcessingUrl("/auth/login_check")
		.usernameParameter("username")
		.passwordParameter("password")
	    .and()
		.logout().logoutSuccessUrl("/login?logout")
	    .and()
	        .csrf()
	    .and()
		.rememberMe().tokenRepository(persistentTokenRepository())
		.tokenValiditySeconds(1209600);
	}
	
	@Bean
	public PersistentTokenRepository persistentTokenRepository() {
		JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImpl();
		db.setDataSource(dataSource);
		return db;
	}
	
	@Bean
	public SavedRequestAwareAuthenticationSuccessHandler 
                savedRequestAwareAuthenticationSuccessHandler() {
		
               SavedRequestAwareAuthenticationSuccessHandler auth 
                    = new SavedRequestAwareAuthenticationSuccessHandler();
		auth.setTargetUrlParameter("targetUrl");
		return auth;
	}	
	
}

P.S В конфигурации аннотации http-имя по умолчанию для флажка “запомнить меня” – “запомнить меня”.

6.HTML/Страницы JSP

6.1 В JSP вы можете использовать тег безопасности Spring sec: авторизация , чтобы определить, входит ли этот пользователь в систему с помощью файлов cookie “запомнить меня”.

<%@taglib prefix="sec"
	uri="http://www.springframework.org/security/tags"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page session="true"%>


	

Title : ${title}

Message : ${message}

Welcome : ${pageContext.request.userPrincipal.name} | Logout

# This user is login by "Remember Me Cookies".

# This user is login by username / password.

6.2 Простая форма входа в систему с флажком “запомнить меня”.

   
User:
Password:
Remember Me:

6.3 Страница обновления. Доступ к этой странице разрешен только для входа пользователя с помощью пароля.

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@page session="true"%>


	

Title : Spring Security Remember Me Example - Update Form

Message : This page is for ROLE_ADMIN and fully authenticated only (Remember me cookie is not allowed!)

Update Account Information...

7. Контроллер

Класс контроллера пружины, прочитайте комментарий для пояснения.

package com.mkyong.web.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class MainController {

	@RequestMapping(value = { "/", "/welcome**" }, method = RequestMethod.GET)
	public ModelAndView defaultPage() {

		ModelAndView model = new ModelAndView();
		model.addObject("title", "Spring Security Remember Me");
		model.addObject("message", "This is default page!");
		model.setViewName("hello");
		return model;

	}

	@RequestMapping(value = "/admin**", method = RequestMethod.GET)
	public ModelAndView adminPage() {

		ModelAndView model = new ModelAndView();
		model.addObject("title", "Spring Security Remember Me");
		model.addObject("message", "This page is for ROLE_ADMIN only!");
		model.setViewName("admin");

		return model;

	}

	/**
	 * This update page is for user login with password only.
	 * If user is login via remember me cookie, send login to ask for password again.
	 * To avoid stolen remember me cookie to update info
	 */
	@RequestMapping(value = "/admin/update**", method = RequestMethod.GET)
	public ModelAndView updatePage(HttpServletRequest request) {

		ModelAndView model = new ModelAndView();

		if (isRememberMeAuthenticated()) {
			//send login for update
			setRememberMeTargetUrlToSession(request);
			model.addObject("loginUpdate", true);
			model.setViewName("/login");
			
		} else {
			model.setViewName("update");
		}

		return model;

	}

	/**
	 * both "normal login" and "login for update" shared this form.
	 * 
	 */
	@RequestMapping(value = "/login", method = RequestMethod.GET)
	public ModelAndView login(@RequestParam(value = "error", required = false) String error,
	  @RequestParam(value = "logout", required = false) String logout, 
          HttpServletRequest request) {

		ModelAndView model = new ModelAndView();
		if (error != null) {
			model.addObject("error", "Invalid username and password!");
			
			//login form for update page
                        //if login error, get the targetUrl from session again.
			String targetUrl = getRememberMeTargetUrlFromSession(request);
			System.out.println(targetUrl);
			if(StringUtils.hasText(targetUrl)){
				model.addObject("targetUrl", targetUrl);
				model.addObject("loginUpdate", true);
			}
			
		}

		if (logout != null) {
			model.addObject("msg", "You've been logged out successfully.");
		}
		model.setViewName("login");

		return model;

	}

	/**
	 * Check if user is login by remember me cookie, refer
	 * org.springframework.security.authentication.AuthenticationTrustResolverImpl
	 */
	private boolean isRememberMeAuthenticated() {

		Authentication authentication = 
                    SecurityContextHolder.getContext().getAuthentication();
		if (authentication == null) {
			return false;
		}

		return RememberMeAuthenticationToken.class.isAssignableFrom(authentication.getClass());
	}
	
	/**
	 * save targetURL in session
	 */
	private void setRememberMeTargetUrlToSession(HttpServletRequest request){
		HttpSession session = request.getSession(false);
		if(session!=null){
			session.setAttribute("targetUrl", "/admin/update");
		}
	}

	/**
	 * get targetURL from session
	 */
	private String getRememberMeTargetUrlFromSession(HttpServletRequest request){
		String targetUrl = "";
		HttpSession session = request.getSession(false);
		if(session!=null){
			targetUrl = session.getAttribute("targetUrl")==null?""
                             :session.getAttribute("targetUrl").toString();
		}
		return targetUrl;
	}
	
}

8. Демонстрация

8.1 Доступ к защищенной странице – http://localhost:8080/spring-security-remember-me/admin , система перенаправит пользователя на форму входа в систему. Попробуйте войти в систему с отметкой “запомнить меня”.

8.2 В Google Chrome Настройки – > Показать дополнительные настройки – > Конфиденциальность, Настройка содержимого… – > “Все файлы cookie и данные сайта” – есть два файла cookie для локального хостинга, один для текущего сеанса и один для файлов cookie входа “запомни меня”.

8.3 Сохранена таблица просмотра “постоянные логины”, имя пользователя, серия и токен.

8.4 Перезапустите веб-приложение, перейдите в Chrome “Все файлы cookie и данные сайта” и удалите сеанс браузера “JSESSIONID”. Попробуйте снова зайти на страницу входа в систему. Теперь система “запомнит вас” и автоматически войдет в систему с помощью файлов cookie для входа в вашем браузере.

8.5 Попробуйте зайти на страницу “обновление” – http://localhost:8080/spring-security-remember-me/admin/update , если пользователь входит в систему с помощью файлов cookie “Запомнить меня”, система снова перенаправит пользователя на форму входа. Это хорошая практика, чтобы избежать кражи файлов cookie для обновления сведений о пользователе.

8.6 Сделано.

9. Разное

Некоторые важные уроки весенней безопасности для изучения:

  1. Некоторые важные уроки весенней безопасности для изучения:
  2. Некоторые важные уроки весенней безопасности для изучения:
  3. Некоторые важные уроки весенней безопасности для изучения:
  4. Некоторые важные уроки весенней безопасности для изучения:
  5. организация.каркасная работа.безопасность.веб.аутентификация.запомните. Помните фильтр проверки подлинности

Скачать Исходный Код

Рекомендации

  1. Весенняя Безопасность Помните Меня Ссылки
  2. Наилучшая Практика Использования Файлов Cookie Для Постоянного Входа в Систему
  3. Улучшенная Постоянная Практика Использования Файлов Cookie Для Входа в Систему
  4. Каков наилучший способ реализовать “запомнить меня” для веб-сайта?
  5. Весенний JdbcTemplate javadoc
  6. Вход в форму безопасности Spring С использованием базы данных – XML и Пример аннотации

Оригинал: “https://mkyong.com/spring-security/spring-security-remember-me-example/”