English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Esempio di codice di esempio di integrazione di shiro per il login e i permessi di springmvc

Il flusso di login standard avrà: nome utente non esistente, password errata, errore di captcha, ecc.

Dopo l'integrazione di shiro, la gestione dei permessi di accesso esterni e il controllo dell'accesso dell'applicazione sono delegati a shiro.

Shiro offre due funzioni principali: autenticazione (Authentication) e autorizzazione (Authorization); il ruolo dell'autenticazione è dimostrare che oneself può accedere, di solito nome utente e password, il ruolo dell'autorizzazione è chi può accedere a quali risorse, controllato attraverso il sistema di ruolo e autorizzazione utente sviluppato dai programmatori.

La gestione delle sessioni e la gestione della cache di shiro non sono nel campo di questo articolo.

Di seguito, attraverso il flusso di gestione dell'accesso non riuscito, si introduce l'integrazione di springmvc con shiro.

Dipendenze del progetto:

nome dipendenza  versione
spring 4.1.4.RELEASE
shiro 1.2.2
self4j 1.7.5
log4j 1.2.17

Configura shiro in web.xml

<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

Crea una configurazione di informazioni di shiro per il file spring-context-shiro.xml, utilizzando spring per caricare

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"
  default-lazy-init="true">
  <description>Shiro Configuration</description>
  <!-- 安全认证过滤器 -->
  <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager" />
    <property name="loginUrl" value="/sys/login" />
    <property name="successUrl" value="/sys" />
    <property name="filters">
      <map>
          <!--自定义登录验证过滤器-->
        <entry key="authc" value-ref="formAuthenticationFilter" />
      </map>
    </property>
    <property name="filterChainDefinitions">
      <value>
        /sys/login = authc
        /sys/logout = logout
        /sys/** = user
      </value>
    </property>
  </bean>
  <!-- 定义 Shiro 主要业务对象 -->
  <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="systemAuthorizingRealm" />
    <property name="cacheManager" ref="shiroCacheManager" />
  </bean>
  <!-- 会话ID生成器 -->
  <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/>
  <!-- 会话管理器,设定会话超时及保存 -->
  <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    <!-- 全局会话超时时间(单位毫秒),默认30分钟 -->
    <property name="globalSessionTimeout" value="1800000" />
    <property name="sessionDAO" ref="sessionDAO"/>
  </bean>
  <!-- 会话验证调度器,每30分钟执行一次验证 -->
  <!-- <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler"> -->
  <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler">
    <property name="interval" value="1800000"/>
    <property name="sessionManager" ref="sessionManager"/>
  </bean>
  <!-- sessionDAO保存认证信息 -->
  <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
    <property name="activeSessionsCacheName" value="shiro-activeSessionCache" />
    <property name="cacheManager" ref="shiroCacheManager" />
    <property name="sessionIdGenerator" ref="sessionIdGenerator"/>
  </bean>
  <!-- Cache delle informazioni di autorizzazione degli utenti, utilizzando EhCache -->
  <bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    <property name="cacheManager" ref="cacheManager" />
  </bean>
  <!-- Gestore del ciclo di vita di Shiro -->
  <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
  <!-- Controllo di autorizzazione a livello di metodo AOP -->
  <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
    <property name="proxyTargetClass" value="true" />
  </bean>
  <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager" />
  </bean>
</beans>

Creare un filtro di autenticazione di login FormAuthenticationFilter.java

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.stereotype.Service;
/**
 /* 验证表单(包括验证码)过滤类 */
@Service
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {
  public static final String DEFAULT_CAPTCHA_PARAM = "validateCode";
  private String captchaParam = DEFAULT_CAPTCHA_PARAM;
  public String getCaptchaParam() {
    return captchaParam;
  }
  protected String getCaptcha(ServletRequest request) {
    return WebUtils.getCleanParam(request, getCaptchaParam());
  }
  protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
    String username = getUsername(request);
    String password = getPassword(request);
    String locale = request.getParameter("locale");
    if (password == null) {
      password = "";
    }
    boolean rememberMe = isRememberMe(request);
    String host = getHost(request);
    String captcha = getCaptcha(request);
    return new UsernamePasswordToken(username, password.toCharArray(), locale, rememberMe, host, captcha);
  }
}

Nuova classe di token UsernamePasswordToken.java

package com.chunhui.webservice.modules.sys.security;
/**
 /* Classe di token per utente e password (inclusa la captcha) */
public class UsernamePasswordToken extends org.apache.shiro.authc.UsernamePasswordToken {
  private static final long serialVersionUID = 1L;
  private String captcha;
  private String locale;
  public String getCaptcha() {
    return captcha;
  }
  public void setCaptcha(String captcha) {
    this.captcha = captcha;
  }
  public String getLocale() {
    return locale;
  }
  public void setLocale(String locale) {
    this.locale = locale;
  }
  public UsernamePasswordToken() {
    super();
  }
  public UsernamePasswordToken(String username, char[] password, boolean rememberMe, String host, String captcha) {
    super(username, password, rememberMe, host);
    this.captcha = captcha;
  }
  public UsernamePasswordToken(String username, char[] password, String locale,boolean rememberMe, String host, String captcha) {
    super(username, password, rememberMe, host);
    this.captcha = captcha;
    this.locale = locale;
  }
}

L'ultimo è la classe di implementazione di autenticazione SystemAuthorizationRealm:

package com.chunhui.webservice.modules.sys.security;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import com.chunhui.webservice.common.utils.EmployeeType;
import com.chunhui.webservice.common.utils.VertifyStatus;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import com.chunhui.webservice.common.servlet.ValidateCodeServlet;
import com.chunhui.webservice.common.utils.SpringContextHolder;
import com.chunhui.webservice.modules.sys.entity.Employee;
import com.chunhui.webservice.modules.sys.entity.Menu;
import com.chunhui.webservice.modules.sys.service.SystemService;
import com.chunhui.webservice.modules.sys.utils.SystemUtils;
import com.chunhui.webservice.modules.sys.web.LoginController;
/**
 * Classe di implementazione della sicurezza del sistema
@Service
@DependsOn({ "employeeDao", "roleDao", "menuDao" })
public class SystemAuthorizingRealm extends AuthorizingRealm {
  private SystemService systemService;
  /**
   * Funzione di callback di autenticazione, chiamata durante il login
   */
  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
    UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
// Giudicare il codice di verifica
    Session session = SecurityUtils.getSubject().getSession();
    // Impostare un timeout di sessione indipendente session.setTimeout(60000);
    String code = (String) session.getAttribute(ValidateCodeServlet.VALIDATE_CODE);
    Se (token.getCaptcha() == null || !token.getCaptcha().toUpperCase().equals(code)) {
      throw new CaptchaException("Errore nel captcha!");
    }
     //Se l'account non esiste, esegui
    //throw new UnknownAccountException();
    //Se l'account è disabilitato, esegui      
    //throw new DisabledAccountException();
    //Salva la lingua selezionata al momento del login
    SecurityUtils.getSubject().getSession().setAttribute("locale", token.getLocale());
    try{
      SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(new Principal(employee), employee.getPassword(), getName());
      return info;
    }
      t.printStackTrace();
      throw new AuthenticationException();
    }
  }
   * Funzione di callback di ricerca dell'autorizzazione, chiamata quando non ci sono informazioni di autorizzazione dell'utente nel cache
   */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    Principal principal = (Principal) getAvailablePrincipal(principals);
    Employee employee = getSystemService().getEmployeeByName(principal.getUsername());
    if (employee != null) {
      SystemUtils.putCache("employee", employee);
      SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
      List<Menu> list = SystemUtils.getMenuList();
      per (Menu menu : list) {
        if (StringUtils.isNotBlank(menu.getPermission())) {
          // Aggiungi informazioni di permesso basate su Permission
          for (String permission : StringUtils.split(menu.getPermission(), ",")) {
            info.addStringPermission(permission);
          }
        }
      }
      // Aggiorna l'IP di login e l'ora
      getSystemService().updateEmployeeLoginInfo(employee.getId());
      return info;
    } else {
      return null;
    }
  }
  /**
   * Svuota l'autenticazione dei permessi associati all'utente, per essere nuovamente caricata l'ultima volta utilizzata
   */
  public void clearCachedAuthorizationInfo(String principal) {
    SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
    clearCachedAuthorizationInfo(principals);
  }
  /**
   * Svuota tutte le autenticazioni associate
   */
  public void clearAllCachedAuthorizationInfo() {
    Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
    if (cache != null) {
      for (Object key : cache.keys()) {
        cache.remove(key);
      }
    }
  }
  /**
   * Ottieni l'oggetto di business del sistema
   */
  public SystemService getSystemService() {
    if (systemService == null) {
      systemService = SpringContextHolder.getBean(SystemService.class);
    }
    return systemService;
  }
  /**
   * Informazioni utente autorizzate
   */
  public static class Principal implements Serializable {
    private static final long serialVersionUID = 1L;
    private String id;
    private String username;
    private String realname;
    private Map<String, Object> cacheMap;
    public Principal(Employee employee) {
      this.id = employee.getId();
      this.username = employee.getUsername();
      this.realname = employee.getRealname();
    }
    public String getId() {
      return id;
    }
    public String getUsername() {
      return username;
    }
    public String getRealname() {
      return realname;
    }
    public Map<String, Object> getCacheMap() {
      if (cacheMap == null) {
        cacheMap = new HashMap<String, Object>();
      }
      return cacheMap;
    }
  }
}

Allora nella pagina JSP, è possibile ottenere il tipo specifico di eccezione dell'eccezione di login per visualizzare la ragione dell'errore nella pagina

<%String error = (String) request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);%>
       <c:set var="exp_type" value="<%=error %>"/>
      <c:set var="tips" value=""></c:set>
      <c:if test="${fn:contains(exp_type,'CaptchaException')}">
        <c:set var="tips" value="Codice di verifica errato"></c:set>
      </c:if>
      <c:if test="${fn:contains(exp_type,'FailVertifyException')}">
        <c:set var="tips" value="L'account non ha superato l'approvazione, non è permesso il login!"></c:set>
      </c:if>
      <c:if test="${fn:contains(exp_type,'NotVertifyException')}">
        <c:set var="tips" value="L'account è in revisione... Non è permesso il login!"></c:set>
      </c:if>
      <c:if test="${fn:contains(exp_type,'UnknownAccountException')}">
        <c:set var="tips" value="L'account non esiste!"></c:set>
      </c:if>
      <c:if test="${fn:contains(exp_type,'DisabledAccountException')}">
        <c:set var="tips" value="L'account non è autorizzato a登录!"></c:set>
      </c:if>
      <c:if test="${fn:contains(exp_type,'IncorrectCredentialsException')}">
        <c:set var="tips" value="Password errata!"></c:set>
      </c:if>

Questo è tutto il contenuto dell'articolo, speriamo che sia utile per la tua apprendimento, e speriamo che tu sostenga fortemente la guida a urla.

Dichiarazione: il contenuto di questo articolo è stato raccolto da Internet, di proprietà del rispettivo autore, il contenuto è stato contribuito e caricato autonomamente dagli utenti di Internet, questo sito non possiede i diritti di proprietà, non è stato editato manualmente e non assume responsabilità legali correlate. Se trovi contenuti sospetti di copyright, ti preghiamo di inviare una e-mail a: notice#oldtoolbag.com (al momento dell'invio dell'e-mail, sostituisci # con @) per segnalare, fornendo prove pertinenti. Una volta verificato, questo sito cancellerà immediatamente i contenuti sospetti di copyright.

Ti potrebbe interessare