Shrio:自定义表单拦截器 FormAuthenticationFilter 登陆认证,并登陆后重定向原请求

设置拦截器 ShiroFilterFactoryBean

方法1. JAVA中设置

	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		// 必须设置 SecurityManager
		shiroFilterFactoryBean.setSecurityManager(securityManager);

		shiroFilterFactoryBean.setLoginUrl("/login");
		shiroFilterFactoryBean.setSuccessUrl("/index");
		shiroFilterFactoryBean.setUnauthorizedUrl("/403");

		// private Map filters; shiro有一些默认的拦截器
		// 比如auth,它就是FormAuthenticationFilter表单拦截器 <取名,拦截器地址>,可以自定义拦截器放在这
		// private Map filterChainDefinitionMap; 哪些路径会被此拦截器拦截到

		// 拦截器.
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		// 配置不会被拦截的链接 顺序判断
		filterChainDefinitionMap.put("/static/**", "anon");
		filterChainDefinitionMap.put("/ajaxLogin", "anon");
		filterChainDefinitionMap.put("/项目的Namespace/userlogin", "anon");
		filterChainDefinitionMap.put("/swagger-ui.html#", "anon");

		// 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边
		// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问;user:remember me的可以访问-->
		filterChainDefinitionMap.put("/fine", "user");
		filterChainDefinitionMap.put("/项目的Namespace/**", "authc");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		System.out.println("Shiro拦截器工厂类注入成功");
		return shiroFilterFactoryBean;
	}

方法2. applicationContext.xml 中设置

<bean id="securityManager"
		class="com.key.common.plugs.security.MyDefaultWebSecurityManager">
		<property name="realm" ref="shiroDbRealm" />
		<property name="rememberMeManager" ref="rememberMeManager" />
	</bean>

	<bean id="formAuthFilter"
		class="com.key.common.plugs.security.FormAuthenticationWithLockFilter">
		<property name="maxLoginAttempts" value="100" />
		<property name="successAdminUrl" value="/main.action?menu=3" />
		<property name="successAdminRole" value="admin" />
		<property name="rememberMeParam" value="rememberMe" />
	</bean>

	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<!-- 系统登陆 -->
		<property name="loginUrl" value="/login.jsp" />
		<!-- 登陆成功的action -->
		<property name="successUrl" value="/login/main.action" />
		<!-- 登陆失败的url跳转 -->
		<property name="unauthorizedUrl" value="/login.jsp?una=0" />
		<property name="filters">
			<util:map>
				<entry key="authc" value-ref="formAuthFilter">
				</entry>
			</util:map>
		</property>
		<property name="filterChainDefinitions">
			<value>
				/login.jsp = authc
				/ic/** = user
				/项目的Namespace/** = user
				/项目的Namespace/** = user
				/sys/** = roles[admin]
			
		
	

认证

package com.key.common.plugs.security;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import com.key.common.base.entity.User;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;

import com.key.common.base.service.AccountManager;

public class FormAuthenticationWithLockFilter extends FormAuthenticationFilter {
	Log log=LogFactory.getLog(FormAuthenticationWithLockFilter.class);

    private long  maxLoginAttempts = 10;

    public static ConcurrentHashMap<String, AtomicLong> accountLockMap   = new ConcurrentHashMap<String, AtomicLong>();
    
    private String successAdminUrl;
  
    private String successAdminRole;
    
    
    @Autowired
    protected AccountManager accountManager;
    
    @Override
    public boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
        AuthenticationToken token = createToken(request, response);
        if (token == null) {
            String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken "
                    + "must be created in order to execute a login attempt.";
            throw new IllegalStateException(msg);
        }
        if (checkIfAccountLocked(request)) {
            return onLoginFailure(token, new ExcessiveAttemptsException(), request, response);
        } else {
            if (!doLogin(request, response, token)) {
                resetAccountLock(getUsername(request));
                return false;
            }
            return true;
        }
    }

    /* 检查账户锁定状态 */
    public boolean checkIfAccountLocked(ServletRequest request) {
        String username = getUsername(request);
        if (username!=null && accountLockMap.get((String) username) != null) {
            long remainLoginAttempts = accountLockMap.get((String) username).get();
            if (remainLoginAttempts <= 0) {
                return true;
            }
        }
        return false;
    }

    
    private boolean doLogin(ServletRequest request, ServletResponse response, AuthenticationToken token)
            throws Exception {
        try {
        	//shrio的subject
            Subject subject = getSubject(request, response);
            subject.login(token);
            
//    		User user = accountManager.findUserByLoginName(getUsername(request));
    		User user = accountManager.findUserByLoginNameOrEmail(getUsername(request));

            return onLoginSuccess(token, subject, request, response);
        } catch (IncorrectCredentialsException e) {//用户名或信息错误
            decreaseAccountLoginAttempts(request);//减少账户登陆尝试次数
            checkIfAccountLocked(request);
            return onLoginFailure(token, e, request, response);
        } catch (AuthenticationException e) {//认证错误
            return onLoginFailure(token, e, request, response);
        }
    }

    /* 减少账户登陆尝试次数 */
    public void decreaseAccountLoginAttempts(ServletRequest request) {
        AtomicLong initValue = new AtomicLong(maxLoginAttempts);
        AtomicLong remainLoginAttempts = accountLockMap.putIfAbsent(getUsername(request), new AtomicLong(maxLoginAttempts));
        if (remainLoginAttempts == null) {
            remainLoginAttempts = initValue;
        }
        remainLoginAttempts.getAndDecrement();
        accountLockMap.put(getUsername(request), remainLoginAttempts);
    }

    public void resetAccountLock(String username) {
        accountLockMap.put(username, new AtomicLong(maxLoginAttempts));
    }

    public void setMaxLoginAttempts(long maxLoginAttempts) {
        this.maxLoginAttempts = maxLoginAttempts;
    }
    
    public void setSuccessAdminUrl(String successAdminUrl) {
		this.successAdminUrl = successAdminUrl;
	}
    
    public void setSuccessAdminRole(String successAdminRole) {
		this.successAdminRole = successAdminRole;
	}
    
    /* 得到某个账号还可以登录次数 */
    public Long getAccountLocked(String username){
   	 long remainLoginAttempts=0;
        if (username!=null && accountLockMap.get((String) username) != null) {
            remainLoginAttempts = accountLockMap.get((String) username).get();
        }
        return remainLoginAttempts+1;
   }
    /* 重写登录失败,加入了失败时还可以重试的次数信息 */
    @Override
    protected boolean onLoginFailure(AuthenticationToken token,
    		AuthenticationException e, ServletRequest request,
    		ServletResponse response) {
    	request.setAttribute("remainLoginAttempt", getAccountLocked(getUsername(request)));
    	return super.onLoginFailure(token, e, request, response);
    }
    
    
    @Override
    protected String getUsername(ServletRequest request) {
    	// TODO Auto-generated method stub
    	String username = super.getUsername(request);
    	if(username==null){
    		Object temp=request.getAttribute(getUsernameParam());
    		username=temp!=null?temp.toString():null;
    	}
    	return username;
    }
    @Override
    protected String getPassword(ServletRequest request) {
    	String password = super.getPassword(request);
    	if(password==null){
    		Object temp=request.getAttribute(getPasswordParam());
    		password=temp!=null?temp.toString():null;
    	}
    	return password;
    }
    
    @Override
    protected boolean isRememberMe(ServletRequest request) {
//    	 TODO Auto-generated method stub
    	return super.isRememberMe(request);
    }

}

部分参考文章
shiro表单拦截器FormAuthenticationFilter,登录成功后如何继续访问原请求

org.apache.shiro.web.filter.authc.FormAuthenticationFilter

你可能感兴趣的:(Shrio)