При разработке вэб приложения рано или поздно необходимо решать задачу безопасности. В этом вопросе Spring Security предоставляет комплексные решения безопасности, аутентификации и авторизации. Построенный на основе Spring Framework, Spring Security имеет все преимущества Dependecy Injection и AOP
Конфигурация Spring Security начинается со следующих моментов:
package spitter.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.
configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.
configuration.EnableWebMvcSecurity;
@Configuration//1
@EnableWebMvcSecurity//2
public class SecurityConfig
extends WebSecurityConfigurerAdapter { //3
}
Важно обратить внимание на
- 1 - обозначить наш класс как спринг конфигурацию
- 2 - аннотация @EnableWebMvcSecurity, которая "включает" Spring Security
- 3 - @EnableWebMvcSecurity не будет работать, если наш класс не наследует WebSecurityConfigurerAdapter или WebSecurityConfigurerAdapter как в нашем примере
Сама конфигурация происходит через переопределение одного из методов configure:
- configure(WebSecurity)
- configure(HttpSecurity)
- configure(AuthenticationManagerBuilder)
Вот пример самой простой конфигурации (через http basic):
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
Этот пример нам говорит о том, что все http запросы к нашему приложению должны быть аутентифицированы(authorizeRequests().anyRequest().authenticated()) и логин происходит через преконфигуренную логин форму и логин страницу(formLogin()).
Следующий шаг конфигурации - это подготовка хранилища юзеров для аутентификации, специализировать моменты, где нужна аутентификация, а где - нет, предоставить свою логин пейджу
Самый простой способо воспользоваться "in-memory" хранищем:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
Можно провести аутентификацию через базу данных:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(
"select name, password_hash, true from users where name=?")
.authoritiesByUsernameQuery(
"SELECT name, id"
+ " FROM roles where id in "
+ "(SELECT role_id FROM jt_roles where user_id in "
+ "(SELECT id FROM users where name = ?) )")
.passwordEncoder(new BCryptPasswordEncoder());
}
Конфигурем логин пейджу
registry.addViewController("/login").setViewName("admin/login");
Eсли у нашего приложения есть админка и мы хотим обезопасить доступ только к этой админке(1, путь - /admin/**) и наша собственная логин страница(2) :
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").authenticated()//1
.and()
.formLogin().loginPage("/login").failureUrl("/login?error"); //2
}
Если кроме юзеров и ролей вам нужно еще выбрать пермишены и у вас более сложная настройко, то удобно делать конфигурацию через UserDetailsService. Для этого нам нужно реализовать интрефейс с одним методом, который должен вернуть объект типа UserDetails:
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
В моем примере это выглядит так:
@Component("userDetailsService")
public class PermissionCentricUserDetailsService implements UserDetailsService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(final String login) {
log.debug("Authenticating {}", login);
String lcLogin = login.toLowerCase();
Optional dbUser = userRepository.findOneByName(lcLogin);
return dbUser
.map(u -> {
List grantedRoles = u.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toList());
return new PermissionCentricUserDetails(lcLogin, u.getId(), u.getPasswordHash(),
grantedRoles, u.getRoles());
})
.orElseThrow(() -> new UsernameNotFoundException("No such user: " + lcLogin));
}
}
....
public class PermissionCentricUserDetails extends User {
...
}
//User реализует интерфейс UserDetails
Это все базовые моменты, которые касаются конфигурацией на уровне web. Дальше рассмотрим секьюрити на уровне методов. Базовые настройки:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//1
@ComponentScan(basePackages = {"com.getman.security"})
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
}
Мы исользуем аннотацию(1) @EnableGlobalMethodSecurity чтобы секьюрити через методы стало доступным. Указываем какого именно типа аннотоция должна стать доступна. В данном случае @PreAuthorize. Можно использовать следуюшие типы аннотаций:
- @Secured - базовая спринговая аннотация, если мы просим доступ к аннотированному методу, но проходим аутентификацию, получаем - исключение Spring Security
- @RolesAllowed - то же самое, что и @Secured, только стандартная java аннотация(JSR-250)
- @PreAuthorize, @PostAuthorize - выбросим исключение, если не пройдем авторизацию, но в первом случае метод не будет вызван, во втором будет(на основе выражения, переданного аннотации)
- @PostFilter, @PreFilter - в первом случае фильтруем результат, во втором - входные параметры на основе выражения, которое передаем аннотации
Имеем 4 аннотации, которые принимают SpEL(Spring Expression language) выражения - @PreAuthorize, @PostAuthorize, @PostFilter, @PreFilter. В моем примере можно увидеть:
@PreAuthorize("@securityUtils.hasPermission('VIEW_CUSTOMERS')")
@RequestMapping(value = "/customerRecord",method = RequestMethod.GET)
public String viewCustomerRecord(Model model, @RequestParam Optional id) {
if (id.isPresent()) {
customer = customerRepository.findOne(id.get());
Iterable orderByCustomer =
customerOrderRepository.findByCustomer(customer);
Iterator iterator = orderByCustomer.iterator();
order = iterator.hasNext() ? iterator.next() : null;
}
model.addAttribute("customerRecord", customer);
model.addAttribute("order", order);
return "admin/index";
}
...
@Component
public final class SecurityUtils {
...
/**
* Checks currently authenticated user for having specified {@link Permission} among roles.
*
* @param permission toString()
representation of {@link Permission}
* @return true if the specified permission is found in any of the user's roles, false otherwise.
*/
public static boolean hasPermission(String permission) {
return hasPermission(Permission.valueOf(permission));
}
/**
* Checks currently authenticated user for having specified {@link Permission} among roles.
*
* @param permission {@link Permission} instance.
* @return true if the specified permission is found in any of the user's roles, false otherwise.
*/
public static boolean hasPermission(Permission permission) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (permission != null && authentication != null) {
Object principal = authentication.getPrincipal();
if (principal instanceof PermissionCentricUserDetails) {
return
((PermissionCentricUserDetails) principal)
.getPermissions()
.contains(permission);
}
}
return false;
}
}
На мой взгяд это удобно для рест сервиса, а для обычного веб приложения хватит обычное web аутентификация. В целом фреймворк очень удобный как с точки зрения быстрой настройки секьюрити, так и с точки зрения более продвинутых фич. Вот мой код с двумя модулями: initial (без секьюрити) и base-security(защищенное)
WebSecurityConfigurerAdapter или WebSecurityConfigurerAdapter
ОтветитьУдалитьо_О
+1 ))
Удалить@Override
ОтветитьУдалитьprotected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password("password").
roles("USER")
.and()
.withUser("admin")
.password("password")
.roles("USER", "ADMIN");
}
Вот это счастье не работает (Spring Boot)
можете сказать возможную причину
Консоли от корпорации Microsoft не сразу захватили всемирную известность и доверие игроков. Первая консоль под названием Xbox, вышедшая в далеком 2001 году, существенно уступала PlayStation 2 по количеству проданных приставок. Однако все изменилось с выходом Xbox 360 - консоли седьмого поколения, которая стала по-настоящему "народной" для жителей России и стран СНГ - Программы для FreeBoot. Сайт Ru-Xbox.Ru является популярным ресурсом в числе поклонников приставки, поскольку он предлагает игры для Xbox 360, которые поддерживают все имеющиеся версии прошивок - совершенно бесплатно! Зачем играть на оригинальном железе, если есть эмуляторы? Для Xbox 360 игры выходили длительное время и находятся как посредственными проектами, так и хитами, многие из которых даже сегодня остаются эксклюзивными для это консоли. Некие пользователи, желающие сыграть в игры для Xbox 360, могут задать вопрос: для чего нужны игры для прошитых Xbox 360 freeboot либо разными версиями LT, если есть эмулятор? Рабочий эмулятор Xbox 360 хоть и существует, но он требует производительного ПК, для покупки которого потребуется вложить существенную сумму. К тому же, различные артефакты в виде исчезающих текстур, отсутствия некоторых графических эффектов и освещения - смогут значительно испортить впечатления об игре и отбить желание для ее дальнейшего прохождения. Что предлагает этот сайт? Наш интернет-сайт вполне приурочен к играм для приставки Xbox 360. У нас вы можете совершенно бесплатно и без регистрации скачать игры на Xbox 360 через торрент для следующих версий прошивок консоли: - FreeBoot; - LT 3.0; - LT 2.0; - LT 1.9. Каждая прошивка имеет свои особенности обхода встроенной защиты. Потому, для запуска той либо иной игры будет нужно скачать специальную ее версию, которая вполне приспособлена под одну из 4 перечисленных выше прошивок. На нашем интернет-сайте вы можете без усилий подобрать желаемый проект под подходящую прошивку, так как возле каждой игры находится название версии (FreeBoot, LT 3.0/2.0/1.9), под которую она адаптирована. Пользователям данного ресурса доступна особая категория игр для 360-го, созданных для Kinect - специального дополнения, которое считывает все движения одного или нескольких игроков, и позволяет управлять с помощью их компьютерными персонажами. Большой выбор ПО Кроме способности загрузить игры на Xbox 360 Freeboot или LT различных версий, здесь можно найти программное обеспечение для консоли от Майкрософт: - всевозможные версии Dashboard, которые позволяют кастомизировать интерфейс консоли под свои нужды, сделав его более комфортным и нынешним; - браузеры; - просмотрщики файлов; - сохранения для игр; - темы для консоли; - программы, для конвертации образов и записи их на диск. Кроме вышеперечисленного игры на Xbox 360 Freeboot можно запускать не с дисковых, а с USB и прочих носителей, используя программу x360key, которую можно достать на нашем интернет-сайте. Посетителям доступно множество полезных статей, а также форум, где вы можете пообщаться с единомышленниками либо попросить совета у более опытнейших хозяев консоли.
ОтветитьУдалить