SlideShare a Scribd company logo
JSUG
b1a9idps
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門


Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
MANAGER STAFF
STAFF
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
@Configuration @EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserDetailsManager userDetailsManager;
public WebSecurityConfig(UserDetailsManager userDetailsManager) {
this.userDetailsManager = userDetailsManager;
}
@Bean
public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/users/create").hasRole("OWNER", "MANAGER")
.antMatchers("/users/delete/{id}").hasRole("OWNER")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").defaultSuccessUrl("/users", true)
.and().logout().logoutSuccessUrl("/login").permitAll()
.and().csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsManager)
.passwordEncoder(passwordEncoder());
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// "/users/create" OWNER MANAGER
.antMatchers("/users/create").hasAnyRole("OWNER", "MANAGER")
// "/users/delete/{id}" OWNER MANAGER
.antMatchers(“/users/delete/{id}").hasRole("OWNER")
//
.anyRequest().authenticated()
// FORM "/login" "/users"
.and().formLogin().loginPage("/login").defaultSuccessUrl("/users", true)
// "/login"
.and().logout().logoutSuccessUrl("/login").permitAll()
// CSRF
.and().csrf().disable();
}
Form認証で学ぶSpring Security入門
public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>,
UsernamePasswordAuthenticationFilter> {
public FormLoginConfigurer() {
// UsernamePasswordAuthenticationFilter AuthenticationFilter
super(new UsernamePasswordAuthenticationFilter(), null);
// Form username "username"
usernameParameter(“username");
// Form password "password"
passwordParameter("password");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// UserDetailsService.java PasswordEncoder.java
auth.userDetailsService(userDetailsManager)
.passwordEncoder(passwordEncoder());
}
Form認証で学ぶSpring Security入門
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
//
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest
= new UsernamePasswordAuthenticationToken(username, password);
setDetails(request, authRequest);
// AuthenticationManager
return this.getAuthenticationManager().authenticate(authRequest);
}
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
protected final UserDetails retrieveUser(String username,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
prepareTimingAttackProtection();
try {
//
UserDetails loadedUser
= this.getUserDetailsService().loadUserByUsername(username);
if (loadedUser == null) {
throw new InternalAuthenticationServiceException(
"UserDetailsService returned null, which is an interface contract
violation");
}
return loadedUser;
} catch (UsernameNotFoundException ex) {
mitigateAgainstTimingAttack(authentication);
throw ex;
} catch (InternalAuthenticationServiceException ex) {
throw ex;
} catch (Exception ex) {
throw new InternalAuthenticationServiceException(ex.getMessage(), ex);
}
}
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials"));
}
String presentedPassword = authentication.getCredentials().toString();
//
if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
logger.debug(
"Authentication failed: password does not match stored value");
throw new BadCredentialsException(messages.getMessage(
"AbstractUserDetailsAuthenticationProvider.badCredentials",
"Bad credentials”));
}
}
@Service
public class UserDetailsManager implements UserDetailsService {
private final UserRepository userRepository;
public UserDetailsManager(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
return userRepository.findByUsername(username)
.map(AuthenticatedUser::new)
.orElseThrow(
() -> new UsernameNotFoundException("username not found"));
}
}
public class AuthenticatedUser implements UserDetails {
private final Integer id;
private final String name;
private final String username;
private final String password;
private final Role role;
//
public Integer getId() { return id; }
public String getName() { return name; }
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return createAuthorityList("ROLE_" + role.name());
}
@Override
public String getPassword() { return password; }
@Override
public String getUsername() { return username; }
@Override
public boolean isAccountNonExpired() { return true; }
@Override
public boolean isAccountNonLocked() { return true; }
@Override
public boolean isCredentialsNonExpired() { return true; }
@Override
public boolean isEnabled() { return true; }
}


Form認証で学ぶSpring Security入門


Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
public interface AccessDecisionVoter<S> {
int ACCESS_GRANTED = 1;
int ACCESS_ABSTAIN = 0;
int ACCESS_DENIED = -1;




Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
@Bean
public RoleHierarchy roleHierarchy(SecurityRolesProperties rolesProperties) {
return rolesProperties.getRoleHierarchy();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/users/create").hasRole("MANAGER")
.antMatchers("/users/delete/{id}").hasRole("OWNER")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/users", true)
.and()
.logout().logoutSuccessUrl("/login").permitAll()
.and()
.csrf().disable();
}
@Bean
public RoleHierarchy roleHierarchy(SecurityRolesProperties rolesProperties) {
// RoleHierarchyImpl.java Bean
return rolesProperties.getRoleHierarchy();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// Role MANAGER
.antMatchers("/users/create").hasRole("MANAGER")
.antMatchers("/users/delete/{id}").hasRole("OWNER")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/users", true)
.and()
.logout().logoutSuccessUrl("/login").permitAll()
.and()
.csrf().disable();
}
@Component
@ConfigurationProperties("security.roles")
public class SecurityRolesProperties {
private Map<String, List<String>> hierarchyMap = new LinkedHashMap<>();
public Map<String, List<String>> getHierarchyMap() {
return hierarchyMap;
}
public void setHierarchyMap(Map<String, List<String>> hierarchyMap) {
this.hierarchyMap = hierarchyMap;
}
public RoleHierarchy getRoleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy =
isEmpty(hierarchyMap) ? "" : roleHierarchyFromMap(hierarchyMap);
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
}
@Component
@ConfigurationProperties("security.roles")
public class SecurityRolesProperties {
private Map<String, List<String>> hierarchyMap = new LinkedHashMap<>();
public Map<String, List<String>> getHierarchyMap() {
return hierarchyMap;
}
public void setHierarchyMap(Map<String, List<String>> hierarchyMap) {
this.hierarchyMap = hierarchyMap;
}
public RoleHierarchy getRoleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy =
isEmpty(hierarchyMap) ? "" : roleHierarchyFromMap(hierarchyMap);
// Hierarchy
// hierarchy = "ROLE_OWNER > ROLE_MANAGERnROLE_MANAGER > ROLE_STAFFn"
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
}
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門
// Role OWNER
@PreAuthorize("hasRole('OWNER')")
public List<User> list() {
return userRepository.findAll();
}
// role "OWNER"
@PreAuthorize("#role == 'OWNER'")
public List<User> list(String role) {
return userRepository.findAll();
}
// request.name "ruchitate"
@PreAuthorize("#r.name == 'ruchitate'")
public List<User> list(@P("r") UserRequest request) {
return userRepository.findAll();
}
// returnObject
@PostAuthorize("returnObject != null && returnObject.username == 'ruchitate'")
public User get(Integer id) {
return userRepository.findById(id).orElse(null);
}
// filterObject
@PreFilter("filterObject.name.equals('ruchitate')")
public List<User> list(List<UserRequest> requests) {
List<String> usernameList = requests.stream()
.map(UserRequest::getName)
.collect(Collectors.toList());
return userRepository.findAllByUsernameIn(usernameList);
}
// filterObject
@PostFilter("filterObject.username == 'ruchitate'")
public List<User> list() {
return userRepository.findAll();
}
@Override
// Bean
@PostFilter("@roleEvaluator.hasRole(principal, filterObject.role)")
public List<UserDto> findAll() {
List<UserDto> userDtoList = new ArrayList<>();
userRepository.findAll().iterator()
.forEachRemaining(user -> userDtoList.add(UserDto.newUserDto(user)));
return userDtoList;
}
@Override
@PostAuthorize("returnObject != null && @roleEvaluator.hasRole(principal,
returnObject.role)")
public UserDto findOne(Integer id) {
return userRepository.findById(id)
.map(UserDto::newUserDto)
.get();
}
@Override
// MANAGER or OWNER
@PreAuthorize("hasRole('MANAGER')")
public UserDto create(UserCreateForm form) {
User user = new User();
BeanUtils.copyProperties(form, user, "password");
user.setPassword(passwordEncoder.encode(form.getPassword()));
return UserDto.newUserDto(userRepository.save(user));
}
@Override
@PreAuthorize("hasRole('OWNER')")
public void delete(Integer id) {
User user = userRepository.findById(id)
.filter(u -> u.getRole() != Role.OWNER)
.orElseThrow(NotAllowedOperationException::new);
userRepository.delete(user);
}
Form認証で学ぶSpring Security入門
dependencies {
testImplementation 'org.springframework.security:spring-security-test'
}
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
@Nested @SpringBootTest
class ListTest {
@Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
@BeforeEach
void beforeEach() {
// SecurityFilter
mockMvc = webAppContextSetup(context).apply(springSecurity()).build();
}
@Test
void success() throws Exception {
User user = new User();
user.setId(1);
user.setName(" ");
user.setUsername("ruchitate");
user.setPassword("12345678");
user.setRole(Role.OWNER);
mockMvc.perform(get("/users")
//
.with(user(new AuthenticatedUser(user))))
.andExpect(status().isOk());
}
}
@Test
//
@WithUserDetails(value = "yaragaki", userDetailsServiceBeanName =
"userDetailsManager")
void findAllForManager() {
List<UserDto> result = userService.findAll();
// Role
Assertions.assertThat(result)
.extracting(
UserDto::getId,
UserDto::getName,
UserDto::getAge,
UserDto::getGender,
UserDto::getRole)
.containsExactly(
Tuple.tuple(2, " ", 31, WOMAN, MANAGER),
Tuple.tuple(3, " ", 24, MAN, STAFF));
}
@Test
@WithUserDetails(value = "ruchitate", userDetailsServiceBeanName =
"userDetailsManager")
void deleteForOwner() {
userService.delete(2);
Assertions.assertThatThrownBy(() -> userService.findOne(2))
.isInstanceOf(NotFoundException.class);
}
@Test
@WithUserDetails(value = "yaragaki", userDetailsServiceBeanName =
"userDetailsManager")
void deleteForManager() {
Assertions.assertThatThrownBy(() -> userService.delete(3))
.isInstanceOf(AccessDeniedException.class);
}
@Test
void loginSuccess() throws Exception {
MvcResult result
//
= mockMvc.perform(formLogin().user("ruchitate").password("12345678"))
.andReturn();
Assertions.assertThat(result.getResponse())
.extracting(
MockHttpServletResponse::getStatus,
MockHttpServletResponse::getRedirectedUrl)
.containsExactly(HttpStatus.FOUND.value(), "/users");
}
@Test
void loginFailed() throws Exception {
MvcResult result
= mockMvc.perform(formLogin().user("ruchitate").password("test"))
.andReturn();
Assertions.assertThat(result.getResponse())
.extracting(
MockHttpServletResponse::getStatus,
MockHttpServletResponse::getRedirectedUrl)
.containsExactly(HttpStatus.FOUND.value(), "/login?error");
}
Form認証で学ぶSpring Security入門
Form認証で学ぶSpring Security入門

More Related Content

What's hot (20)

PDF
SQLアンチパターン - ジェイウォーク
ke-m kamekoopa
 
PDF
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
Y Watanabe
 
PDF
メルカリ・ソウゾウでは どうGoを活用しているのか?
Takuya Ueda
 
PPTX
KeycloakでAPI認可に入門する
Hitachi, Ltd. OSS Solution Center.
 
PPTX
モノリスからマイクロサービスへの移行 ~ストラングラーパターンの検証~(Spring Fest 2020講演資料)
NTT DATA Technology & Innovation
 
PDF
マイクロにしすぎた結果がこれだよ!
mosa siru
 
PDF
入社1年目のプログラミング初心者がSpringを学ぶための手引き
土岐 孝平
 
KEY
やはりお前らのMVCは間違っている
Koichi Tanaka
 
PDF
これからのネイティブアプリにおけるOpenID Connectの活用
Masaru Kurahayashi
 
PDF
FridaによるAndroidアプリの動的解析とフッキングの基礎
ken_kitahara
 
PDF
Dockerfile を書くためのベストプラクティス解説編
Masahito Zembutsu
 
PDF
ソーシャルゲーム案件におけるDB分割のPHP実装
infinite_loop
 
PDF
クラウド環境下におけるAPIリトライ設計
Kouji YAMADA
 
PPTX
世界一わかりやすいClean Architecture
Atsushi Nakamura
 
PDF
Always on 可用性グループ 構築時のポイント
Masayuki Ozawa
 
PPTX
Spring Boot Tutorial
Naphachara Rattanawilai
 
PDF
Spring Framework - Spring Security
Dzmitry Naskou
 
PPTX
NGINXをBFF (Backend for Frontend)として利用した話
Hitachi, Ltd. OSS Solution Center.
 
PDF
Microsoft Graph APIを活用した社内アプリケーション開発
Yuki Hattori
 
SQLアンチパターン - ジェイウォーク
ke-m kamekoopa
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
Y Watanabe
 
メルカリ・ソウゾウでは どうGoを活用しているのか?
Takuya Ueda
 
KeycloakでAPI認可に入門する
Hitachi, Ltd. OSS Solution Center.
 
モノリスからマイクロサービスへの移行 ~ストラングラーパターンの検証~(Spring Fest 2020講演資料)
NTT DATA Technology & Innovation
 
マイクロにしすぎた結果がこれだよ!
mosa siru
 
入社1年目のプログラミング初心者がSpringを学ぶための手引き
土岐 孝平
 
やはりお前らのMVCは間違っている
Koichi Tanaka
 
これからのネイティブアプリにおけるOpenID Connectの活用
Masaru Kurahayashi
 
FridaによるAndroidアプリの動的解析とフッキングの基礎
ken_kitahara
 
Dockerfile を書くためのベストプラクティス解説編
Masahito Zembutsu
 
ソーシャルゲーム案件におけるDB分割のPHP実装
infinite_loop
 
クラウド環境下におけるAPIリトライ設計
Kouji YAMADA
 
世界一わかりやすいClean Architecture
Atsushi Nakamura
 
Always on 可用性グループ 構築時のポイント
Masayuki Ozawa
 
Spring Boot Tutorial
Naphachara Rattanawilai
 
Spring Framework - Spring Security
Dzmitry Naskou
 
NGINXをBFF (Backend for Frontend)として利用した話
Hitachi, Ltd. OSS Solution Center.
 
Microsoft Graph APIを活用した社内アプリケーション開発
Yuki Hattori
 

Similar to Form認証で学ぶSpring Security入門 (12)

PDF
Lesson07_Spring_Security_API.pdf
Scott Anderson
 
PDF
From 0 to Spring Security 4.0
robwinch
 
PPTX
Java EE 8 security and JSON binding API
Alex Theedom
 
PDF
Lesson07-UsernamePasswordAuthenticationFilter.pdf
Scott Anderson
 
PPTX
Simple blog wall creation on Java
Max Titov
 
PPTX
Spring Security 3
Jason Ferguson
 
PDF
Lesson_07_Spring_Security_Register_NEW.pdf
Scott Anderson
 
PPTX
springb security.pptxdsdsgfdsgsdgsdgsdgdsgdsgds
zmulani8
 
PDF
The hidden gems of Spring Security
Massimiliano Dessì
 
PDF
Java Web Application Security with Java EE, Spring Security and Apache Shiro ...
Matt Raible
 
PDF
Spring5 hibernate5 security5 lab step by step
Rajiv Gupta
 
PDF
Java Web Application Security with Java EE, Spring Security and Apache Shiro ...
Matt Raible
 
Lesson07_Spring_Security_API.pdf
Scott Anderson
 
From 0 to Spring Security 4.0
robwinch
 
Java EE 8 security and JSON binding API
Alex Theedom
 
Lesson07-UsernamePasswordAuthenticationFilter.pdf
Scott Anderson
 
Simple blog wall creation on Java
Max Titov
 
Spring Security 3
Jason Ferguson
 
Lesson_07_Spring_Security_Register_NEW.pdf
Scott Anderson
 
springb security.pptxdsdsgfdsgsdgsdgsdgdsgdsgds
zmulani8
 
The hidden gems of Spring Security
Massimiliano Dessì
 
Java Web Application Security with Java EE, Spring Security and Apache Shiro ...
Matt Raible
 
Spring5 hibernate5 security5 lab step by step
Rajiv Gupta
 
Java Web Application Security with Java EE, Spring Security and Apache Shiro ...
Matt Raible
 
Ad

More from Ryosuke Uchitate (9)

PDF
決済サービスのSpring Bootのバージョンを2系に上げた話
Ryosuke Uchitate
 
PDF
パラレルキャリアがもたらす相乗効果
Ryosuke Uchitate
 
PDF
Micrometerでメトリクスを収集してAmazon CloudWatchで可視化
Ryosuke Uchitate
 
PDF
オレはIntelliJ IDEAをこう使っている
Ryosuke Uchitate
 
PDF
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Ryosuke Uchitate
 
PDF
春だしBannerで遊バナいか?
Ryosuke Uchitate
 
PDF
ユニットテストのアサーション 流れるようなインターフェースのAssertJを添えて 入門者仕立て
Ryosuke Uchitate
 
PPTX
Spring超入門-Springと出会ってから1年半-
Ryosuke Uchitate
 
PPTX
Spring starterによるSpring Boot Starter
Ryosuke Uchitate
 
決済サービスのSpring Bootのバージョンを2系に上げた話
Ryosuke Uchitate
 
パラレルキャリアがもたらす相乗効果
Ryosuke Uchitate
 
Micrometerでメトリクスを収集してAmazon CloudWatchで可視化
Ryosuke Uchitate
 
オレはIntelliJ IDEAをこう使っている
Ryosuke Uchitate
 
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Ryosuke Uchitate
 
春だしBannerで遊バナいか?
Ryosuke Uchitate
 
ユニットテストのアサーション 流れるようなインターフェースのAssertJを添えて 入門者仕立て
Ryosuke Uchitate
 
Spring超入門-Springと出会ってから1年半-
Ryosuke Uchitate
 
Spring starterによるSpring Boot Starter
Ryosuke Uchitate
 
Ad

Recently uploaded (20)

PPTX
Presentation on Foundation Design for Civil Engineers.pptx
KamalKhan563106
 
PPT
IISM Presentation.ppt Construction safety
lovingrkn
 
PDF
Geothermal Heat Pump ppt-SHRESTH S KOKNE
SHRESTHKOKNE
 
PDF
BEE331-Week 04-SU25.pdf semiconductors UW
faemoxley
 
PDF
Natural Language processing and web deigning notes
AnithaSakthivel3
 
PPTX
ISO/IEC JTC 1/WG 9 (MAR) Convenor Report
Kurata Takeshi
 
PDF
1_ISO Certifications by Indian Industrial Standards Organisation.pdf
muhammad2010960
 
PPTX
Unit-1&2,mdngmnd,mngmdnmgnmdnfmngdf.pptx
jayarao21
 
PDF
Comparative Analysis of the Use of Iron Ore Concentrate with Different Binder...
msejjournal
 
PDF
th International conference on Big Data, Machine learning and Applications (B...
Zac Darcy
 
PDF
LEARNING CROSS-LINGUAL WORD EMBEDDINGS WITH UNIVERSAL CONCEPTS
kjim477n
 
PDF
SMART HOME AUTOMATION PPT BY - SHRESTH SUDHIR KOKNE
SHRESTHKOKNE
 
PDF
POWER PLANT ENGINEERING (R17A0326).pdf..
haneefachosa123
 
PPTX
Fluid statistics and Numerical on pascal law
Ravindra Kolhe
 
PDF
ADVXAI IN MALWARE ANALYSIS FRAMEWORK: BALANCING EXPLAINABILITY WITH SECURITY
ijscai
 
PPTX
UNIT III CONTROL OF PARTICULATE CONTAMINANTS
sundharamm
 
PDF
The Complete Guide to the Role of the Fourth Engineer On Ships
Mahmoud Moghtaderi
 
PPT
04 Origin of Evinnnnnnnnnnnnnnnnnnnnnnnnnnl-notes.ppt
LuckySangalala1
 
PDF
Call For Papers - International Journal on Natural Language Computing (IJNLC)
kevig
 
PDF
PRIZ Academy - Change Flow Thinking Master Change with Confidence.pdf
PRIZ Guru
 
Presentation on Foundation Design for Civil Engineers.pptx
KamalKhan563106
 
IISM Presentation.ppt Construction safety
lovingrkn
 
Geothermal Heat Pump ppt-SHRESTH S KOKNE
SHRESTHKOKNE
 
BEE331-Week 04-SU25.pdf semiconductors UW
faemoxley
 
Natural Language processing and web deigning notes
AnithaSakthivel3
 
ISO/IEC JTC 1/WG 9 (MAR) Convenor Report
Kurata Takeshi
 
1_ISO Certifications by Indian Industrial Standards Organisation.pdf
muhammad2010960
 
Unit-1&2,mdngmnd,mngmdnmgnmdnfmngdf.pptx
jayarao21
 
Comparative Analysis of the Use of Iron Ore Concentrate with Different Binder...
msejjournal
 
th International conference on Big Data, Machine learning and Applications (B...
Zac Darcy
 
LEARNING CROSS-LINGUAL WORD EMBEDDINGS WITH UNIVERSAL CONCEPTS
kjim477n
 
SMART HOME AUTOMATION PPT BY - SHRESTH SUDHIR KOKNE
SHRESTHKOKNE
 
POWER PLANT ENGINEERING (R17A0326).pdf..
haneefachosa123
 
Fluid statistics and Numerical on pascal law
Ravindra Kolhe
 
ADVXAI IN MALWARE ANALYSIS FRAMEWORK: BALANCING EXPLAINABILITY WITH SECURITY
ijscai
 
UNIT III CONTROL OF PARTICULATE CONTAMINANTS
sundharamm
 
The Complete Guide to the Role of the Fourth Engineer On Ships
Mahmoud Moghtaderi
 
04 Origin of Evinnnnnnnnnnnnnnnnnnnnnnnnnnl-notes.ppt
LuckySangalala1
 
Call For Papers - International Journal on Natural Language Computing (IJNLC)
kevig
 
PRIZ Academy - Change Flow Thinking Master Change with Confidence.pdf
PRIZ Guru
 

Form認証で学ぶSpring Security入門

  • 8.
  • 15. @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private final UserDetailsManager userDetailsManager; public WebSecurityConfig(UserDetailsManager userDetailsManager) { this.userDetailsManager = userDetailsManager; } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/users/create").hasRole("OWNER", "MANAGER") .antMatchers("/users/delete/{id}").hasRole("OWNER") .anyRequest().authenticated() .and().formLogin().loginPage("/login").defaultSuccessUrl("/users", true) .and().logout().logoutSuccessUrl("/login").permitAll() .and().csrf().disable(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsManager) .passwordEncoder(passwordEncoder()); } }
  • 16. @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // "/users/create" OWNER MANAGER .antMatchers("/users/create").hasAnyRole("OWNER", "MANAGER") // "/users/delete/{id}" OWNER MANAGER .antMatchers(“/users/delete/{id}").hasRole("OWNER") // .anyRequest().authenticated() // FORM "/login" "/users" .and().formLogin().loginPage("/login").defaultSuccessUrl("/users", true) // "/login" .and().logout().logoutSuccessUrl("/login").permitAll() // CSRF .and().csrf().disable(); }
  • 18. public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> { public FormLoginConfigurer() { // UsernamePasswordAuthenticationFilter AuthenticationFilter super(new UsernamePasswordAuthenticationFilter(), null); // Form username "username" usernameParameter(“username"); // Form password "password" passwordParameter("password"); }
  • 19. @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // UserDetailsService.java PasswordEncoder.java auth.userDetailsService(userDetailsManager) .passwordEncoder(passwordEncoder()); }
  • 21. public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { if (postOnly && !request.getMethod().equals("POST")) { throw new AuthenticationServiceException( "Authentication method not supported: " + request.getMethod()); } // String username = obtainUsername(request); String password = obtainPassword(request); if (username == null) { username = ""; } if (password == null) { password = ""; } username = username.trim(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); setDetails(request, authRequest); // AuthenticationManager return this.getAuthenticationManager().authenticate(authRequest); }
  • 25. protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { prepareTimingAttackProtection(); try { // UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username); if (loadedUser == null) { throw new InternalAuthenticationServiceException( "UserDetailsService returned null, which is an interface contract violation"); } return loadedUser; } catch (UsernameNotFoundException ex) { mitigateAgainstTimingAttack(authentication); throw ex; } catch (InternalAuthenticationServiceException ex) { throw ex; } catch (Exception ex) { throw new InternalAuthenticationServiceException(ex.getMessage(), ex); } }
  • 26. protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { if (authentication.getCredentials() == null) { logger.debug("Authentication failed: no credentials provided"); throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } String presentedPassword = authentication.getCredentials().toString(); // if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) { logger.debug( "Authentication failed: password does not match stored value"); throw new BadCredentialsException(messages.getMessage( "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials”)); } }
  • 27. @Service public class UserDetailsManager implements UserDetailsService { private final UserRepository userRepository; public UserDetailsManager(UserRepository userRepository) { this.userRepository = userRepository; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { return userRepository.findByUsername(username) .map(AuthenticatedUser::new) .orElseThrow( () -> new UsernameNotFoundException("username not found")); } }
  • 28. public class AuthenticatedUser implements UserDetails { private final Integer id; private final String name; private final String username; private final String password; private final Role role; // public Integer getId() { return id; } public String getName() { return name; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return createAuthorityList("ROLE_" + role.name()); } @Override public String getPassword() { return password; } @Override public String getUsername() { return username; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } }
  • 29.
  • 31.
  • 34. public interface AccessDecisionVoter<S> { int ACCESS_GRANTED = 1; int ACCESS_ABSTAIN = 0; int ACCESS_DENIED = -1;
  • 45. @Bean public RoleHierarchy roleHierarchy(SecurityRolesProperties rolesProperties) { return rolesProperties.getRoleHierarchy(); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/users/create").hasRole("MANAGER") .antMatchers("/users/delete/{id}").hasRole("OWNER") .anyRequest().authenticated() .and() .formLogin().loginPage("/login").defaultSuccessUrl("/users", true) .and() .logout().logoutSuccessUrl("/login").permitAll() .and() .csrf().disable(); }
  • 46. @Bean public RoleHierarchy roleHierarchy(SecurityRolesProperties rolesProperties) { // RoleHierarchyImpl.java Bean return rolesProperties.getRoleHierarchy(); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // Role MANAGER .antMatchers("/users/create").hasRole("MANAGER") .antMatchers("/users/delete/{id}").hasRole("OWNER") .anyRequest().authenticated() .and() .formLogin().loginPage("/login").defaultSuccessUrl("/users", true) .and() .logout().logoutSuccessUrl("/login").permitAll() .and() .csrf().disable(); }
  • 47. @Component @ConfigurationProperties("security.roles") public class SecurityRolesProperties { private Map<String, List<String>> hierarchyMap = new LinkedHashMap<>(); public Map<String, List<String>> getHierarchyMap() { return hierarchyMap; } public void setHierarchyMap(Map<String, List<String>> hierarchyMap) { this.hierarchyMap = hierarchyMap; } public RoleHierarchy getRoleHierarchy() { RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); String hierarchy = isEmpty(hierarchyMap) ? "" : roleHierarchyFromMap(hierarchyMap); roleHierarchy.setHierarchy(hierarchy); return roleHierarchy; } }
  • 48. @Component @ConfigurationProperties("security.roles") public class SecurityRolesProperties { private Map<String, List<String>> hierarchyMap = new LinkedHashMap<>(); public Map<String, List<String>> getHierarchyMap() { return hierarchyMap; } public void setHierarchyMap(Map<String, List<String>> hierarchyMap) { this.hierarchyMap = hierarchyMap; } public RoleHierarchy getRoleHierarchy() { RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); String hierarchy = isEmpty(hierarchyMap) ? "" : roleHierarchyFromMap(hierarchyMap); // Hierarchy // hierarchy = "ROLE_OWNER > ROLE_MANAGERnROLE_MANAGER > ROLE_STAFFn" roleHierarchy.setHierarchy(hierarchy); return roleHierarchy; } }
  • 51. // Role OWNER @PreAuthorize("hasRole('OWNER')") public List<User> list() { return userRepository.findAll(); } // role "OWNER" @PreAuthorize("#role == 'OWNER'") public List<User> list(String role) { return userRepository.findAll(); } // request.name "ruchitate" @PreAuthorize("#r.name == 'ruchitate'") public List<User> list(@P("r") UserRequest request) { return userRepository.findAll(); }
  • 52. // returnObject @PostAuthorize("returnObject != null && returnObject.username == 'ruchitate'") public User get(Integer id) { return userRepository.findById(id).orElse(null); }
  • 53. // filterObject @PreFilter("filterObject.name.equals('ruchitate')") public List<User> list(List<UserRequest> requests) { List<String> usernameList = requests.stream() .map(UserRequest::getName) .collect(Collectors.toList()); return userRepository.findAllByUsernameIn(usernameList); }
  • 54. // filterObject @PostFilter("filterObject.username == 'ruchitate'") public List<User> list() { return userRepository.findAll(); }
  • 55. @Override // Bean @PostFilter("@roleEvaluator.hasRole(principal, filterObject.role)") public List<UserDto> findAll() { List<UserDto> userDtoList = new ArrayList<>(); userRepository.findAll().iterator() .forEachRemaining(user -> userDtoList.add(UserDto.newUserDto(user))); return userDtoList; } @Override @PostAuthorize("returnObject != null && @roleEvaluator.hasRole(principal, returnObject.role)") public UserDto findOne(Integer id) { return userRepository.findById(id) .map(UserDto::newUserDto) .get(); }
  • 56. @Override // MANAGER or OWNER @PreAuthorize("hasRole('MANAGER')") public UserDto create(UserCreateForm form) { User user = new User(); BeanUtils.copyProperties(form, user, "password"); user.setPassword(passwordEncoder.encode(form.getPassword())); return UserDto.newUserDto(userRepository.save(user)); } @Override @PreAuthorize("hasRole('OWNER')") public void delete(Integer id) { User user = userRepository.findById(id) .filter(u -> u.getRole() != Role.OWNER) .orElseThrow(NotAllowedOperationException::new); userRepository.delete(user); }
  • 59. @Nested @SpringBootTest class ListTest { @Autowired private WebApplicationContext context; private MockMvc mockMvc; @BeforeEach void beforeEach() { // SecurityFilter mockMvc = webAppContextSetup(context).apply(springSecurity()).build(); } @Test void success() throws Exception { User user = new User(); user.setId(1); user.setName(" "); user.setUsername("ruchitate"); user.setPassword("12345678"); user.setRole(Role.OWNER); mockMvc.perform(get("/users") // .with(user(new AuthenticatedUser(user)))) .andExpect(status().isOk()); } }
  • 60. @Test // @WithUserDetails(value = "yaragaki", userDetailsServiceBeanName = "userDetailsManager") void findAllForManager() { List<UserDto> result = userService.findAll(); // Role Assertions.assertThat(result) .extracting( UserDto::getId, UserDto::getName, UserDto::getAge, UserDto::getGender, UserDto::getRole) .containsExactly( Tuple.tuple(2, " ", 31, WOMAN, MANAGER), Tuple.tuple(3, " ", 24, MAN, STAFF)); }
  • 61. @Test @WithUserDetails(value = "ruchitate", userDetailsServiceBeanName = "userDetailsManager") void deleteForOwner() { userService.delete(2); Assertions.assertThatThrownBy(() -> userService.findOne(2)) .isInstanceOf(NotFoundException.class); } @Test @WithUserDetails(value = "yaragaki", userDetailsServiceBeanName = "userDetailsManager") void deleteForManager() { Assertions.assertThatThrownBy(() -> userService.delete(3)) .isInstanceOf(AccessDeniedException.class); }
  • 62. @Test void loginSuccess() throws Exception { MvcResult result // = mockMvc.perform(formLogin().user("ruchitate").password("12345678")) .andReturn(); Assertions.assertThat(result.getResponse()) .extracting( MockHttpServletResponse::getStatus, MockHttpServletResponse::getRedirectedUrl) .containsExactly(HttpStatus.FOUND.value(), "/users"); } @Test void loginFailed() throws Exception { MvcResult result = mockMvc.perform(formLogin().user("ruchitate").password("test")) .andReturn(); Assertions.assertThat(result.getResponse()) .extracting( MockHttpServletResponse::getStatus, MockHttpServletResponse::getRedirectedUrl) .containsExactly(HttpStatus.FOUND.value(), "/login?error"); }