spring security core plugin 五(Authentication)

Basic and Digest Authentication

 

 

PropertyDefaultDescription

useBasicAuth

false

Whether to use Basic authentication

basic.realmName

“Grails Realm”

Realm name displayed in the browser authentication popup

basic.credentialsCharset

“UTF-8”

The character set used to decode Base64-encoded data

如果使用Basic Authentication,那么会显示标准浏览器的登录对话框而不会跳到登录页面。

grails.plugin.springsecurity.filterChain.chainMap = [
   [pattern: '/webservice/**', filters: 'JOINED_FILTERS,-exceptionTranslationFilter'],
   [pattern: '/**',            filters: 'JOINED_FILTERS,-basicAuthenticationFilter,-basicExceptionTranslationFilter']
]

Digest Authentication和Basic类似,但是它更安全,因为经过了hash。

 

PropertyDefault ValueMeaning

useDigestAuth

false

Whether to use Digest authentication

digest.realmName

“Grails Realm”

Realm name displayed in the browser popup

digest.key

“changeme”

Key used to build the nonce for authentication; it should be changed but that’s not required

digest.nonceValiditySeconds

300

How long a nonce stays valid

digest.passwordAlreadyEncoded

false

Whether you are managing the password hashing yourself

digest.createAuthenticatedToken

false

If true, creates an authenticated UsernamePasswordAuthenticationToken to avoid loading the user from the database twice. However, this process skips the isAccountNonExpired()isAccountNonLocked()isCredentialsNonExpired(), and isEnabled() checks, so it is not advised.

digest.useCleartextPasswords

false

If true, a cleartext password encoder is used (not recommended). If false, passwords hashed by DigestAuthPasswordEncoder are stored in the database

Certificate(X.509) Login Authentication

这需要HTTPS,需要服务端配置一个客户端的证书, 如果证书有效,可以从证书中提取到用户名,只要数据库中有这个用户,就可以免密登录 。

 

PropertyDefault ValueMeaning

useX509

false

Whether to support certificate-based logins

x509.continueFilterChainOnUnsuccessfulAuthentication

true

Whether to proceed when an authentication attempt fails to allow other authentication mechanisms to process the request

x509.subjectDnRegex

“CN=(.*?)(?:,|$)”

Regular expression for extracting the username from the certificate’s subject name

x509.checkForPrincipalChanges

false

Whether to re-extract the username from the certificate and check that it’s still the current user when a valid Authentication already exists

x509.invalidateSessionOnPrincipalChange

true

Whether to invalidate the session if the principal changed (based on a checkForPrincipalChanges check)

x509.subjectDnClosure

none

If set, the plugin’s ClosureX509PrincipalExtractor class is used to extract information from the X.509 certificate using the specified closure

x509.throwExceptionWhenTokenRejected

false

If true thrown a BadCredentialsException

Remember-Me Cookie

这是一个可选项,通过勾选框可以选择是否使用cookie。

 

PropertyDefault ValueMeaning

rememberMe.cookieName

grails_remember_me

remember-me cookie name; should be unique per application

rememberMe.cookieDomain

none

remember-me cookie domain

rememberMe.alwaysRemember

false

If true, create a remember-me cookie even if no checkbox is on the form

rememberMe.tokenValiditySeconds

1209600 (14 days)

Max age of the cookie in seconds

rememberMe.parameter

remember-me

Login form remember-me checkbox name

rememberMe.key

grailsRocks

Value used to encode cookies; should be unique per application

rememberMe.useSecureCookie

none

Whether to use a secure cookie or not; if true a secure cookie is created, if false a non-secure cookie is created, and if not set, a secure cookie is created if the request used HTTPS

rememberMe.createSessionOnSuccess

true

Whether to create a session of one doesn’t exist to ensure that the Authentication is stored for future requests

rememberMe.persistent

false

If true, stores persistent login information in the database

rememberMe.persistentToken.domainClassName

none

Domain class used to manage persistent logins

rememberMe.persistentToken.seriesLength

16

Number of characters in the cookie’s series attribute

rememberMe.persistentToken.tokenLength

16

Number of characters in the cookie’s token attribute

atr.rememberMeClass

RememberMeAuthenticationToken

remember-me authentication class

 

ajaxLogin.js
var onLogin;

$.ajaxSetup({
   beforeSend: function(jqXHR, event) {
      if (event.url != $("#ajaxLoginForm").attr("action")) {
         // save the 'success' function for later use if
         // it wasn't triggered by an explicit login click
         onLogin = event.success;
      }
   },
   statusCode: {
      // Set up a global Ajax error handler to handle 401
      // unauthorized responses. If a 401 status code is
      // returned the user is no longer logged in (e.g. when
      // the session times out), so re-display the login form.
      401: function() {
         showLogin();
      }
   }
});

function showLogin() {
   var ajaxLogin = $("#ajaxLogin");
   ajaxLogin.css("text-align", "center");
   ajaxLogin.jqmShow();
}

function logout(event) {
   event.preventDefault();
   $.ajax({
      url: $("#_logout").attr("href"),
      method: "POST",
      success: function(data, textStatus, jqXHR) {
         window.location = "/";
      },
      error: function(jqXHR, textStatus, errorThrown) {
         console.log("Logout error, textStatus: " + textStatus +
                     ", errorThrown: " + errorThrown);
      }
   });
}

function authAjax() {
   $("#loginMessage").html("Sending request ...").show();

   var form = $("#ajaxLoginForm");
   $.ajax({
      url:       form.attr("action"),
      method:   "POST",
      data:      form.serialize(),
      dataType: "JSON",
      success: function(json, textStatus, jqXHR) {
         if (json.success) {
            form[0].reset();
            $("#loginMessage").empty();
            $("#ajaxLogin").jqmHide();
            $("#loginLink").html(
               'Logged in as ' + json.username +
               ' (<a href="' + $("#_logout").attr("href") +
               '" id="logout">Logout</a>)');
            $("#logout").click(logout);
            if (onLogin) {
               // execute the saved event.success function
               onLogin(json, textStatus, jqXHR);
            }
         }
         else if (json.error) {
            $("#loginMessage").html('<span class="errorMessage">' +
                                    json.error + "</error>");
         }
         else {
            $("#loginMessage").html(jqXHR.responseText);
         }
      },
      error: function(jqXHR, textStatus, errorThrown) {
         if (jqXHR.status == 401 && jqXHR.getResponseHeader("Location")) {
            // the login request itself wasn't allowed, possibly because the
            // post url is incorrect and access was denied to it
            $("#loginMessage").html('<span class="errorMessage">' +
               'Sorry, there was a problem with the login request</error>');
         }
         else {
            var responseText = jqXHR.responseText;
            if (responseText) {
               var json = $.parseJSON(responseText);
               if (json.error) {
                  $("#loginMessage").html('<span class="errorMessage">' +
                                          json.error + "</error>");
                  return;
               }
            }
            else {
               responseText = "Sorry, an error occurred (status: " +
                              textStatus + ", error: " + errorThrown + ")";
            }
            $("#loginMessage").html('<span class="errorMessage">' +
                                    responseText + "</error>");
         }
      }
   });
}

$(function() {
   $("#ajaxLogin").jqm({ closeOnEsc: true });
   $("#ajaxLogin").jqmAddClose("#cancelLogin");
   $("#ajaxLoginForm").submit(function(event) {
      event.preventDefault();
      authAjax();
   });
   $("#authAjax").click(authAjax);
   $("#logout").click(logout);
});
ajaxLogin.css
#ajaxLogin {
   padding:    0px;
   text-align: center;
   display:    none;
}

#ajaxLogin .inner {
   width:              400px;
   padding-bottom:     6px;
   margin:             60px auto;
   text-align:         left;
   border:             1px solid #aab;
   background-color:   #f0f0fa;
   -moz-box-shadow:    2px 2px 2px #eee;
   -webkit-box-shadow: 2px 2px 2px #eee;
   -khtml-box-shadow:  2px 2px 2px #eee;
   box-shadow:         2px 2px 2px #eee;
}

#ajaxLogin .inner .fheader {
   padding:          18px 26px 14px 26px;
   background-color: #f7f7ff;
   margin:           0px 0 14px 0;
   color:            #2e3741;
   font-size:        18px;
   font-weight:      bold;
}

#ajaxLogin .inner .cssform p {
   clear:         left;
   margin:        0;
   padding:       4px 0 3px 0;
   padding-left:  105px;
   margin-bottom: 20px;
   height:        1%;
}

#ajaxLogin .inner .cssform input[type="text"],
#ajaxLogin .inner .cssform input[type="password"] {
   width: 150px;
}

#ajaxLogin .inner .cssform label {
   font-weight:   bold;
   float:         left;
   text-align:    right;
   margin-left:  -105px;
   width:         150px;
   padding-top:   3px;
   padding-right: 10px;
}

.ajaxLoginButton {
   background-color: #efefef;
   font-weight: bold;
   padding: 0.5em 1em;
   display: -moz-inline-stack;
   display: inline-block;
   vertical-align: middle;
   white-space: nowrap;
   overflow: visible;
   text-decoration: none;
      -moz-border-radius: 0.3em;
   -webkit-border-radius: 0.3em;
           border-radius: 0.3em;
}

.ajaxLoginButton:hover, .ajaxLoginButton:focus {
   background-color: #999999;
   color: #ffffff;
}

#ajaxLogin .inner .login_message {
   padding: 6px 25px 20px 25px;
   color:   #c33;
}

#ajaxLogin .inner .text_ {
   width: 120px;
}

#ajaxLogin .inner .chk {
   height: 12px;
}

.errorMessage {
   color: red;
}

_ajaxLogin.gsp

<span id="logoutLink" style="display: none;">
<g:link elementId='_logout' controller='logout'>Logout</g:link>
</span>

<span id="loginLink" style="position: relative; margin-right: 30px; float: right">
<sec:ifLoggedIn>
   Logged in as <sec:username/> (<g:link elementId='logout' controller='logout'>Logout</g:link>)
</sec:ifLoggedIn>
<sec:ifNotLoggedIn>
   <a href="#" onclick="showLogin(); return false;">Login</a>
</sec:ifNotLoggedIn>
</span>

<div id="ajaxLogin" class="jqmWindow" style="z-index: 3000;">
   <div class="inner">
      <div class="fheader">Please Login..</div>
      <form action="${request.contextPath}/login/authenticate" method="POST"
            id="ajaxLoginForm" name="ajaxLoginForm" class="cssform" autocomplete="off">
         <p>
            <label for="username">Username:</label>
            <input type="text" class="text_" name="username" id="username" />
         </p>
         <p>
            <label for="password">Password</label>
            <input type="password" class="text_" name="password" id="password" />
         </p>
         <p>
            <label for="remember_me">Remember me</label>
            <input type="checkbox" class="chk" id="remember_me" name="remember-me"/>
         </p>
         <p>
            <input type="submit" id="authAjax" name="authAjax"
                   value="Login" class="ajaxLoginButton" />
            <input type="button" id="cancelLogin" value="Cancel"
                   class="ajaxLoginButton" />
         </p>
      </form>
      <div style="display: none; text-align: left;" id="loginMessage"></div>
   </div>
</div>

main.gsp

<html lang="en" class="no-js">
   <head>
      ...
      <g:layoutHead/>
   </head>
   <body>
      <g:render template='/includes/ajaxLogin'/>
      ...
      <g:layoutBody/>
   </body>
</html>

 

Ajax login工作流

 

(1)单击连接来显示登录form

(2)填写验证信息,单击登录

(3)使用Ajax请求进行提交表单

(4)如果验证成功:

 

  • 重定向url:/login/ajaxSuccess
  • 返回json串,串中有一个布尔值success=true,及username
  • 客户端决定登录成功,更新page显示用户已登录

(5)如果验证失败

 

  • 重定向/login/authfail?ajax=true
  • 返回json串中包含一个string,包含错误信息
  • 客户端决定登录失败,更新page显示用户登录失败。

最后欢迎大家访问我的个人网站:1024s​​​​​​​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值