16 Aralık 2019 Pazartesi

SpringSecurity FormLoginConfigurer Sınıfı

Giriş
- Post isteğinde "username" ve "password" ve "remember-me" alanları olmalıdır. usernameParameter() ve passwordParameter() çağrıları ile kullanılacak string sabitleri değiştirilebilir.

- Post isteği MediaType.MULTIPART_FORM_DATA olarak gönderilir

Örnek - Http İstek Parametreleri
İstemci şunu gönderir.
POST /login HTTP/1.1
Host: localhost:8000
cache-control: no-cache
Content-Type: multipart/form-data;boundary=---ABCD
Content-Dispositon: form-data; name="username"

mypassword

Content-Disposition: form-data; name="password"

mypassword
---ABCD

Rest İle Kullanmak - Yani Post Authentication
Bu sınıfı Rest ile kullanmak için yani Rest ile login olmak için failHandler()  ve successHandler() metodlarını çağırarak değer atamak gerekir.

successHandler() metodunu kullanmamızın amacı şu "remove redirect logic on successful authentication"

failHandler() metodunu kullanmamızın amacu şu "Send Http Status 401 instead of 302 on unsuccessful login"

BasicAuthentication İle Farkı
FormAuthentication yöntemi BasicAuthentication yöntemine göre daha çok kullanılıyor. BasicAuthentication yönteminde credentials her istekte tekrar gönderilir. FormAuthentication yönteminde ise sunucu tarafında bir session açılır istemci sessionid bilgisini gönderir

BasicAuthentication için HttpBasicConfigurer kullanılır.

Tanımlama
Bu sınıfın WebSecurityConfigurerAdapter ile kullanılır. Sınıfa @Configuration ve
@EnableWebSecurity anotasyonları ekli olmalıdır. Şöyle yaparız.
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
      ...
      .and()
      .formLogin()
        ...
      .and()
      ...
  }
  ...
}
Pre Authentication Metodları

loginPage metodu
Belirtilen URL'ye hit gelince hangi JSP sayfasının gönderileceğini belirtir. Eğer bu sayfayı belirtmezsek Spring bizim için bir sayfa üretiyor. Şeklen şöyle


Örnek
Elimizde şöyle bir kod olsun.
@Controller
public class LoginController {

  @GetMapping("/showLoginPage")
  public String showLoginPage() {
    return "login";  // your login jsp page
  }
}
login.jsp şöyledir
<form:form action="${pageContext.request.contextPath}/authenticate" method="post">   
  <%-- authenticate=loginProcessingUrl-->
  ...  
</form:form>
Örnek
Şöyle yaparız.
http.authorizeRequests().antMatchers("/settings").hasAuthority("Administrator")
  .anyRequest().authenticated()
  .and()
  .formLogin().permitAll()
    .loginPage("/login").permitAll()
    .defaultSuccessUrl("/dashboard")
    .failureUrl("/login?error")
    .successHandler(authenticationSuccessHandler)
  .and()
  ...
loginProcessingUrl metodu
POST yapılacak adresi belirtir.

Örnek
Elimizde şöyle bir kod olsun.
protected void configure(HttpSecurity http) throws Exception {
http. 
...
.loginPage("/showLoginPage")
.loginProcessingUrl("/authenticate")
JSP formunu şöyle yaparız.
<form:form action="${pageContext.request.contextPath}/authenticate" method="post">   
  <%-- authenticate=loginProcessingUrl-->
  ...  
</form:form>
passwordParameter metodu
Örnek
Şöyle yaparız.
.formLogin().loginPage("/login")
  .usernameParameter("logInId").passwordParameter("password")
Örnek
Şöyle yaparız.
httpSecurity.formLogin().loginPage("/login")
                   .usernameParameter("userId")
                   .passwordParameter("password");
permitAll metodu
/login ve /logout adreslerine herkesin erişebilmesini sağlar.

Eğer başka bir şey yazmazsak örneğin Spring Data Rest ile
spring.data.rest.base-path=myrestapi
şeklinde bir adres kullanıyorsak bu adres otomatik olarak doğrulanmış kullanıcı ister.

usernameParameter metodu
Elimizde şöyle bir html olsun.
<!DOCTYPE html>
<#import "/spring.ftl" as spring />
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="<@spring.url '/login' />" method="post">
    username:<input type="text" name="username"><br>
    password:<input type="password" name="password"><br>
    <input type="submit" value="login">
</form>

</body>
</html>
Şöyle yaparız.
http.authorizeRequests()
  ...
  .and()
  .formLogin()
    .loginPage("/login")
    .failureUrl("/login?error=true")
    .usernameParameter("username")
    .passwordParameter("password")
    .defaultSuccessUrl("/user/welcome")
    .permitAll()
  .and()
  ...

Post Authentication Metodları

defaultSuccessUrl metodu

Şöyle yaparız.
httpSecurity.formLogin().defaultSuccessUrl("/market/products/add")
                                .failureUrl("/login?error");
failHandler metodu
Rest ile kullanmak için aynı successHandler() metodunda olduğu gibi farklı bir Http sonucu göndermek istersek kullanırız.

successHandler metodu
Rest ile kullanmak için SimpleUrlAuthenticationSuccessHandler sınıfından kalıtan bir sınıf kullanılabilir.
Örnek
Şöyle yaparız
.formLogin()
  .successHandler((request, response, authentication) -> {
    response.getWriter().append("OK");
    response.setStatus(HttpServletResponse.SC_OK);
  })
  .failureHandler((request, response, exception) -> {
    response.getWriter().append("Invalid credentials or inactive account");
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
  })
Örnek
Şöyle yaparız.
//Form matching
http.formLogin()
  .usernameParameter("username").passwordParameter("password")
  .loginPage("/login").permitAll()
  .successHandler(authenticationSuccessHandler)
  .failureHandler(new SimpleUrlAuthenticationFailureHandler())
  .and()

Hiç yorum yok:

Yorum Gönder