shiro study notes: remeberMe, multiple login account locked

About shiro implementation of rememberme, before then we use the cookie to achieve, here too, the principle is the same;

But because the use of shiro framework, shiro need to configure cookie and cache, as well as manager object:

<! - Security Manager -> 
    < bean the above mentioned id = "securityManager" class = "org.apache.shiro.web.mgt.DefaultWebSecurityManager" > 
        <! - Cache Manager -> 
        < Property name = "CacheManager" REF = "CacheManager" /> 
        <-! mode sessions -> 
        < Property name = "SessionMode" value = "Native" /> 
        <-! configuration the realm -> 
        < Property name = "Realms" REF = " myRealm "/>
        <property name="rememberMeManager" ref="rememberMeManager"/>
    </bean>

    <!--cookie对象-->
    <bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="rememberMe"/>
        <!--只有http的连接才使用cookie-->
        <property name="httpOnly" value="true"/>
        <!--cookie失效时间-->
        <property name="maxAge" value="#{60*60*24}"/>
    </bean>
    
    <!--记住我管理器对象-->
    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <property name="cookie" ref="simpleCookie"/>
    </bean>

 Controller:

@Controller
public class UserController {

    private static final transient Logger log = LoggerFactory.getLogger(UserController.class);
    @RequestMapping("/login")
    public String login(User user,String rememberMe) throws Exception  {

        Subject currentUser = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
        //记住我
        if (rememberMe != null &&rememberMe.equals("1")) {
            token.setRememberMe(true);
        }
        currentUser.login(token);
        return "redirect:/home";
    }
}

Front page:

<form action="../login" method="post">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="checkbox" name="rememberMe" value="1">记住我
    <input type="submit">
</form>

After the configuration, then the configuration file shiro path configuration:

Represents the emp / under request, the user can access and run tomcat, entry form information, I remember, and then log on, the login is successful, close the browser, close the browser at the same time, closed the session, but the cookie contains data , so you can directly access / emp / ** resources under, pro-test: If the problem can not get out Firefox effect, may be set Firefox to automatically clear the cache when you close the browser needs to close:

Repeatedly locked account login

Multiple login lock account: according to the name of this function, we can ideas, we want to log information on where? If you put a cookie, it will refresh every time you log registration data, there is no way the number of log records, records can be cached logins. To do:

1. Configure cache:

<? Xml Version = "1.0" encoding = "UTF-8" ?> 
< Ehcache name = "es" > 

    < diskStore path = "java.io.tmpdir" /> 

    <-! MaxEntriesLocalHeap: is used to limit the current cache the maximum number of elements in the heap memory can be saved 
    eternal: whether false set of elemen cache never expires 
    timeToLiveSeconds: the survival time of the object, the object refers to the time from creation to fail needs. Only the eternal is false is valid. The default value is 0, which means you can have access. (Unit: seconds) 
   timeToIdleSeconds: When an object is idle, refers to how long the object will fail in not being accessed. Only the eternal is false is valid. The default value is 0. (Unit: seconds) 
    -> 
    <! - the default cache -> 
    < defaultCache
             maxEntriesLocalHeap = "10000" 
            Eternal = "false"="120"
            timeToLiveSeconds="120"
            maxEntriesLocalDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"/>

    <!-- 登录记录缓存 锁定10分钟 -->
    <cache name="passwordRetryCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="360"
           timeToLiveSeconds="360"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="authorizationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="authenticationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="shiro-activeSessionCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="3600"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

</ehcache>
ehcache.xml

2. shiro configuration file, configure the cache path:

3. Customize credentials match, a cache is introduced

package com.zs.credentials;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;

import java.util.concurrent.atomic.AtomicInteger;

public class MyMatcher extends HashedCredentialsMatcher {

    //Map:key,value
    //key:存用户名 value:次数
    privateThe Cache <String, of AtomicInteger> passwordCache; 

    public MyMatcher (the CacheManager CacheManager) {
         the this .passwordCache = cacheManager.getCache ( "passwordRetryCache" ); 
    } 

    // password matches 
    @Override
     public  Boolean doCredentialsMatch (AuthenticationToken token, AuthenticationInfo info) {
         // get the user name 
        String username = (String) token.getPrincipal ();
         // Find the cache if there is to go to the information 
        AtomicInteger retryCount = passwordCache.get (username);
         // the first time was null 
        iF (retryCount == null ) {
            // Initial words: 0 
            retryCount = new new of AtomicInteger (0 );
             // cached in 
            passwordCache.put (username, retryCount); 
        } 
        @ increase in retryCount 1, and acquires the value 
        IF (retryCount.incrementAndGet ()> . 3 ) {
             the throw  new new ExcessiveAttemptsException ( "the account is locked" ); 
        } 
        // password matches 
        Boolean Matcher = Super .doCredentialsMatch (token, info);
         // If the login is successful 
        IF (Matcher) {
             // empty the cache data 
            passwordCache.remove (username); 
        } 
        return Matcher ;
    }
}
Custom credential matcher

The certificate matcher disposed, and the introduction of the cache:

Then run logon test: three incorrect password, login, reported abnormal account locked:

Exception class:

package com.zs.controller;

import com.zs.entity.Result;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class ExceptionController {

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Result error(Exception ex, Model model) {
        Result result = new Result();
        if (ex instanceof AccountException) {
            if (ex instanceof ExcessiveAttemptsException) {
                result.setMessages("账户锁定");
            } else {
                result.setStats(501);
                result.setMessages("账号错误");
            }
        } else if (ex instanceof IncorrectCredentialsException) {
            result.setStats(502);
            result.setMessages("密码错误");
        } else {
            result.setStats(503);
            result.setMessages("数据错误");
        }
        return result;
    }
}
View Code

运行结果:

 

Guess you like

Origin www.cnblogs.com/Zs-book1/p/11354788.html