热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

springbootshirodruid

1、Shiro是Apache下的一个开源项目,我们称之为ApacheShiro。它是一个很易用与Java项目的的安全框架,提供了认证、授权、加密、会话管理,与springSecur

1、Shiro是Apache下的一个开源项目,我们称之为Apache Shiro。它是一个很易用与Java项目的的安全框架,提供了认证、授权、加密、会话管理,与spring Security 一样都是做一个权限的安全框架,但是与Spring Security 相比,在于 Shiro 使用了比较简单易懂易于使用的授权方式。shiro属于轻量级框架,相对于security简单的多,也没有security那么复杂。所以我这里也是简单介绍一下shiro的使用。

2、非常简单;其基本功能点如下图所示:

springboot shiro druid

 

Authentication身份认证/登录,验证用户是不是拥有相应的身份;

Authorization授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;

Session Manager会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;

Cryptography加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;

Web SupportWeb支持,可以非常容易的集成到Web环境;

Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;

Concurrencyshiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;

Testing提供测试支持;

Run As允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;

Remember Me记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

记住一点,Shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供;然后通过相应的接口注入给Shiro即可。

好了 下面直接上代码POM



	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.1.3.RELEASE
		 
	
	com.ruochu
	ruochu
	0.0.1-SNAPSHOT
	ruochu
	人生若如初见,何事秋风悲画扇

	
		1.8
		1.3.2
		2.5
		1.2.5
		1.4.0
		2.0.0
	

	
		
			org.springframework.boot
			spring-boot-starter-web
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
		
            mysql
            mysql-connector-java
            runtime
        
        
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            ${mybatis.boot.version}
        
        
         
            com.alibaba
            druid-spring-boot-starter
            RELEASE
        
         
         	org.springframework.boot
         	
         		spring-boot-configuration-processor
         	
         	true
         
         
            ch.qos.logback
            logback-classic
        
        
            org.slf4j
            jcl-over-slf4j
        
        
        
            org.springframework.boot
            spring-boot-starter-thymeleaf
        
         
         
	        org.springframework.boot
	        spring-boot-devtools
	        true
	    
	    
		
			org.apache.commons
			commons-lang3
		
		
		
			com.github.pagehelper
			pagehelper-spring-boot-starter
			${pagehelper.boot.version}
		
		
		
			org.apache.shiro
			shiro-core
			${shiro.version}
		

		
		
			org.apache.shiro
			shiro-spring
			${shiro.version}
		

		
		
			org.apache.shiro
			shiro-ehcache
			${shiro.version}
		
		
		
			com.github.theborakompanioni
			thymeleaf-extras-shiro
			${thymeleaf.extras.shiro.version}
		
        
	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
		
	


  yml

# 项目相关配置
ruochu:
  # 名称
  name: RuoChu
  # 版本
  version: 1.0.0
  # 版权年份
  copyrightYear: 2019
  # 文件上传路径
  profile: D:/profile/
  # 获取ip地址开关
  addressEnabled: true

# 开发环境配置
server:
  # 服务端口
  port: 80
  servlet:
    # 项目contextPath
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # tomcat最大线程数,默认为200
    max-threads: 800
    # Tomcat启动初始化的线程数,默认值25
    min-spare-threads: 30
# 日志配置
logging:
  level:
    com:
        winterchen:
          dao: DEBUG
#mybatis配置
mybatis:
  #配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*Mapper.xml
spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/rc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezOne=GMT%2B8
      username: root
      password: 
      # 连接池配置
      # 初始化大小,最小,最大
      initial-size: 1
      max-active: 20
      min-idle: 1
      # 配置获取连接等待超时的时间
      max-wait: 10000
      #是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
      pool-prepared-statements: true
      #要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100
      max-open-prepared-statements: 20
      #来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。
      validation-query: SELECT 1 FROM DUAL
      validation-query-timeout: 5000
      #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
      test-on-borrow: false
      #归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
      test-on-return: false
      #建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
      test-while-idle: true
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      time-between-eviction-runs-millis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      min-evictable-idle-time-millis: 30000
      max-evictable-idle-time-millis: 60000
      removeAbandoned: true
      removeAbandonedTimeout: 1800
      connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
      max-pool-prepared-statement-per-connection-size: 20
      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
      filters: stat,wall #filters: #配置多个英文逗号分隔(统计,sql注入,log4j过滤)
 
    type: com.alibaba.druid.pool.DruidDataSource
  # 模板引擎
  thymeleaf:
    mode: HTML
    encoding: utf-8
    prefix: classpath:/templates/
    suffix: .html
    # 禁用缓存
    cache: false
   #热部署
  devtools:
    restart:
      enabled: true
      additional-paths: src/main/java
      exclude: templates/**
# Shiro
shiro:
  user:
    # 登录地址
    loginUrl: /
    # 权限认证失败地址
    unauthorizedUrl: /unauth
    # 首页地址
    indexUrl: /index
    # 验证码开关
    captchaEnabled: true
    # 验证码类型 math 数组计算 char 字符
    captchaType: math
  COOKIE:
    # 设置COOKIE的域名 默认空,即当前访问的域名
    domain: 
    # 设置COOKIE的有效访问路径
    path: /
    # 设置HttpOnly属性
    httpOnly: true
    # 设置COOKIE的过期时间,天为单位
    maxAge: 30
  session:
    # Session超时时间(默认30分钟)
    expireTime: 30
    # 同步session到数据库的周期(默认1分钟)
    dbSyncPeriod: 1
    # 相隔多久检查一次session的有效性,默认就是10分钟
    validationInterval: 10
# 用户配置
user:
  password:
    # 密码错误{maxRetryCount}次锁定10分钟
    maxRetryCount: 5
    

  /ehcache-shiro.xml




    
    

    
    
    

    
    
    


	

 配置shiro

package com.ruochu.config;

import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.Filter;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.COOKIERememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCOOKIE;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.ruochu.common.utils.StringUtils;
import com.ruochu.shiro.AuthRealm;
import com.ruochu.shiro.CredentialMatcher;
import com.ruochu.shiro.web.filter.LogoutFilter;
/**
 * 权限配置加载
 * 
 * @author ruochu
 */
@Configuration
public class ShiroConfig
{
    public static final String PREMISSION_STRING = "perms[\"{0}\"]";

    // Session超时时间,单位为毫秒(默认30分钟)
    @Value("${shiro.session.expireTime}")
    private int expireTime;

    // 相隔多久检查一次session的有效性,单位毫秒,默认就是10分钟
    @Value("${shiro.session.validationInterval}")
    private int validationInterval;

    // 验证码开关
    @Value("${shiro.user.captchaEnabled}")
    private boolean captchaEnabled;

    // 验证码类型
    @Value("${shiro.user.captchaType}")
    private String captchaType;

    // 设置COOKIE的域名
    @Value("${shiro.COOKIE.domain}")
    private String domain;

    // 设置COOKIE的有效访问路径
    @Value("${shiro.COOKIE.path}")
    private String path;

    // 设置HttpOnly属性
    @Value("${shiro.COOKIE.httpOnly}")
    private boolean httpOnly;

    // 设置COOKIE的过期时间,秒为单位
    @Value("${shiro.COOKIE.maxAge}")
    private int maxAge;

    // 登录地址
    @Value("${shiro.user.loginUrl}")
    private String loginUrl;

    // 权限认证失败地址
    @Value("${shiro.user.unauthorizedUrl}")
    private String unauthorizedUrl;

    @Value(value = "${user.password.maxRetryCount}")
    private int  maxRetryCount;
    /**
     * 缓存管理器 使用Ehcache实现
     */
    @Bean
    public EhCacheManager getEhCacheManager()
    {
        net.sf.ehcache.CacheManager cacheManager = net.sf.ehcache.CacheManager.getCacheManager("ruochu");
        EhCacheManager em = new EhCacheManager();
        if (StringUtils.isNull(cacheManager))
        {
            em.setCacheManagerConfigFile("classpath:ehcache/ehcache-shiro.xml");
            return em;
        }
        else
        {
            em.setCacheManager(cacheManager);
            return em;
        }
    }
    /**
     * 自定义Realm
     */
    @Bean
    public AuthRealm userRealm(EhCacheManager cacheManager,@Qualifier("credentialMatcher") CredentialMatcher matcher)
    {
    	AuthRealm userRealm = new AuthRealm();
        userRealm.setCacheManager(cacheManager);
        userRealm.setCredentialsMatcher(matcher);
        return userRealm;
    }

    @Bean("credentialMatcher")
    public CredentialMatcher credentialMatcher() {

        return new CredentialMatcher();

    }
    /**
     * 安全管理器
     */
    @Bean
    public SecurityManager securityManager(AuthRealm userRealm)
    {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(userRealm);
        // 记住我
        securityManager.setRememberMeManager(rememberMeManager());
        // 注入缓存管理器;
        securityManager.setCacheManager(getEhCacheManager());
        // session管理器
        //securityManager.setSessionManager(sessionManager());
        return securityManager;
    }
    
    /**
     * 退出过滤器
     */
    public LogoutFilter logoutFilter()
    {
        LogoutFilter logoutFilter = new LogoutFilter();
        logoutFilter.setLoginUrl(loginUrl);
        return logoutFilter;
    }

    /**
     * Shiro过滤器配置
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
    {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // Shiro的核心安全接口,这个属性是必须的
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 身份认证失败,则跳转到登录页面的配置
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        // 权限认证失败,则跳转到指定页面
        shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
        // Shiro连接约束配置,即过滤链的定义
        LinkedHashMap filterChainDefinitiOnMap= new LinkedHashMap<>();
        // 对静态资源设置匿名访问
        filterChainDefinitionMap.put("/favicon.ico**", "anon");
        filterChainDefinitionMap.put("/ruoyi.png**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/docs/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/ajax/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/ruoyi/**", "anon");
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
        // 退出 logout地址,shiro去清除session
        filterChainDefinitionMap.put("/logout", "logout");
        // 不需要拦截的访问
        filterChainDefinitionMap.put("/login", "anon");
        // 系统权限列表
        // filterChainDefinitionMap.putAll(SpringUtils.getBean(IMenuService.class).selectPermsAll());

        Map filters = new LinkedHashMap<>();
        // 注销成功,则跳转到指定页面
        filters.put("logout", logoutFilter());
        shiroFilterFactoryBean.setFilters(filters);

        // 所有请求需要认证
        //filterChainDefinitionMap.put("/**", "user,onlineSession,syncOnlineSession");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

  

    /**
     * COOKIE 属性设置
     */
    public SimpleCOOKIE rememberMeCOOKIE()
    {
        SimpleCOOKIE COOKIE = new SimpleCOOKIE("rememberMe");
        COOKIE.setDomain(domain);
        COOKIE.setPath(path);
        COOKIE.setHttpOnly(httpOnly);
        COOKIE.setMaxAge(maxAge * 24 * 60 * 60);
        return COOKIE;
    }

    /**
     * 记住我
     */
    public COOKIERememberMeManager rememberMeManager()
    {
        COOKIERememberMeManager COOKIERememberMeManager = new COOKIERememberMeManager();
        COOKIERememberMeManager.setCOOKIE(rememberMeCOOKIE());
        COOKIERememberMeManager.setCipherKey(Base64.decode("fCq+/xW488hMTCD+cmJ3aQ=="));
        return COOKIERememberMeManager;
    }


    /**
     * 开启Shiro注解通知器
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
            @Qualifier("securityManager") SecurityManager securityManager)
    {
        AuthorizationAttributeSourceAdvisor authorizatiOnAttributeSourceAdvisor= new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    @Bean    
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {        
    	DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();        
    	creator.setProxyTargetClass(true);       
    	return creator;    
    }
}

  配置druid

package com.ruochu.config;

import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;

@Configuration
public class DruidConfiguration {
	private static final Logger logger = LoggerFactory.getLogger(DruidConfiguration.class);
    @Value("${spring.datasource.druid.url}")
    private String dbUrl;

    @Value("${spring.datasource.druid.username}")
    private String username;

    @Value("${spring.datasource.druid.password}")
    private String password;

    @Value("${spring.datasource.druid.driver-class-name}")
    private String driverClassName;

    @Value("${spring.datasource.druid.initial-size}")
    private int initialSize;

    @Value("${spring.datasource.druid.min-idle}")
    private int minIdle;

    @Value("${spring.datasource.druid.max-active}")
    private int maxActive;

    @Value("${spring.datasource.druid.max-wait}")
    private int maxWait;

    @Value("${spring.datasource.druid.time-between-eviction-runs-millis}")
    private int timeBetweenEvictionRunsMillis;

    @Value("${spring.datasource.druid.min-evictable-idle-time-millis}")
    private int minEvictableIdleTimeMillis;

    @Value("${spring.datasource.druid.validation-query}")
    private String validationQuery;

    @Value("${spring.datasource.druid.test-while-idle}")
    private boolean testWhileIdle;

    @Value("${spring.datasource.druid.test-on-borrow}")
    private boolean testOnBorrow;

    @Value("${spring.datasource.druid.test-on-return}")
    private boolean testOnReturn;

    @Value("${spring.datasource.druid.pool-prepared-statements}")
    private boolean poolPreparedStatements;

    @Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size}")
    private int maxPoolPreparedStatementPerConnectionSize;

    @Value("${spring.datasource.druid.filters}")
    private String filters;

    @Value("{spring.datasource.druid.connection-properties}")
    private String connectionProperties;

    @Bean     //声明其为Bean实例
    @Primary  //在同样的DataSource中,首先使用被标注的DataSource
    public DataSource dataSource() {
        DruidDataSource datasource = new DruidDataSource();
        datasource.setUrl(dbUrl);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setDriverClassName(driverClassName);
        //configuration
        datasource.setInitialSize(initialSize);
        datasource.setMinIdle(minIdle);
        datasource.setMaxActive(maxActive);
        datasource.setMaxWait(maxWait);
        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        datasource.setValidationQuery(validationQuery);
        datasource.setTestWhileIdle(testWhileIdle);
        datasource.setTestOnBorrow(testOnBorrow);
        datasource.setTestOnReturn(testOnReturn);
        datasource.setPoolPreparedStatements(poolPreparedStatements);
        datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
        try {
            datasource.setFilters(filters);
        } catch (Exception e) {
            logger.error("druid configuration initialization filter", e);
        }
        datasource.setConnectionProperties(connectionProperties);

        return datasource;
    }

    @Bean
    public ServletRegistrationBean druidServlet() {
        //logger.info("init Druid Servlet Configuration ");
        ServletRegistrationBean servletRegistratiOnBean= new ServletRegistrationBean();
        servletRegistrationBean.setServlet(new StatViewServlet());
        servletRegistrationBean.addUrlMappings("/druid/*");
        Map initParameters = new HashMap<>();
        initParameters.put("loginUsername", "admin");// 用户名
        initParameters.put("loginPassword", "123456");// 密码
        initParameters.put("resetEnable", "false");// 禁用HTML页面上的“Reset All”功能
        initParameters.put("allow", ""); // IP白名单 (没有配置或者为空,则允许所有访问)
        //initParameters.put("deny", "192.168.20.38");// IP黑名单 (存在共同时,deny优先于allow)
        servletRegistrationBean.setInitParameters(initParameters);
        return servletRegistrationBean;
    }


    @Bean
    public FilterRegistrationBean druidWebStatViewFilter() {
        FilterRegistrationBean registratiOnBean= new FilterRegistrationBean(new WebStatFilter());
        registrationBean.addInitParameter("urlPatterns", "/*");
        registrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
        return registrationBean;
    }
}

  自定义Realm

package com.ruochu.shiro;


import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.ruochu.model.SysModule;
import com.ruochu.model.SysRole;
import com.ruochu.model.SysUser;
import com.ruochu.service.ISysUserService;
import com.ruochu.shiro.service.SysPasswordService;
import com.ruochu.web.exception.user.CaptchaException;
import com.ruochu.web.exception.user.RoleBlockedException;
import com.ruochu.web.exception.user.UserBlockedException;
import com.ruochu.web.exception.user.UserNotExistsException;
import com.ruochu.web.exception.user.UserPasswordNotMatchException;
import com.ruochu.web.exception.user.UserPasswordRetryLimitExceedException;

/**
 * 自定义Realm 处理登录 权限
 * 
 * @author ruochu
 */
public class AuthRealm extends AuthorizingRealm{
	private final static Logger log = LoggerFactory.getLogger(AuthRealm.class);
	@Autowired
    private ISysUserService userService;
	@Autowired
    private SysPasswordService passwordService;
    
    //认证.登录
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException{
       /* UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        String password = "";
        if (upToken.getPassword() != null)
        {
            password = new String(upToken.getPassword());
        }

        SysUser user = userService.findByLoginName(username);
        boolean passwordflag= passwordService.matches(user, password);
        if(passwordflag) {
        	 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
             return info;
        }else {
            	logger.info("对用户[" + username + "]进行登录验证..验证未通过{}");
                throw new AuthenticationException("对用户[" + username + "]进行登录验证..验证未通过{}");
        }*/
    	 UsernamePasswordToken upToken = (UsernamePasswordToken) token;
         String username = upToken.getUsername();
         String password = "";
         SimpleAuthenticationInfo info =null;
         if (upToken.getPassword() != null)
         {
             password = new String(upToken.getPassword());
         }

         SysUser user = null;
         try
         {
        	 user = userService.findByLoginName(username);
         }
         catch (Exception e)
         {
             log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
             throw new AuthenticationException(e.getMessage(), e);
         }
         try {
        	 info = new SimpleAuthenticationInfo(user, password, getName());
		} catch (Exception e) {
			log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
            throw new AuthenticationException(e.getMessage(), e);
		}
         
         return info;
    }
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
    	SysUser user=(SysUser) principal.fromRealm(this.getClass().getName()).iterator().next();//获取session中的用户
        List permissiOns=new ArrayList<>();
        Set roles = user.getRoles();
        if(roles.size()>0) {
            for(SysRole role : roles) {
                Set modules = role.getModules();
                if(modules.size()>0) {
                    for(SysModule module : modules) {
                        permissions.add(module.getMname());
                    }
                }
            }
        }
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addStringPermissions(permissions);//将权限放入shiro中.
        return info;
    }
}

 

package com.ruochu.shiro;

import java.util.concurrent.atomic.AtomicInteger;

import javax.annotation.PostConstruct;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import com.ruochu.model.SysUser;
import com.ruochu.service.ISysUserService;
import com.ruochu.shiro.service.SysPasswordService;
import com.ruochu.web.exception.user.UserPasswordNotMatchException;

public class CredentialMatcher extends SimpleCredentialsMatcher {    	
	/*	 * 这里是进行密码匹配的方法,自己定义	
	 * 通过用户的唯一标识得到 AuthenticationInfo 然后和 AuthenticationToken (用户名 密码),进行比较
	 * 登陆失败次数统计
	 *  */    
	private final static Logger log = LoggerFactory.getLogger(SysPasswordService.class);
	@Autowired
    private CacheManager cacheManager;
	
	@Autowired
    private ISysUserService userService;
	
	@Autowired
    private SysPasswordService passwordService;

    private Cache loginRecordCache;

    @Value(value = "${user.password.maxRetryCount}")
    private String maxRetryCount;

    @PostConstruct
    public void init()
    {
        loginRecordCache = cacheManager.getCache("passwordRetryCache");
    }
	@Override    
	public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
		UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;  
		 String loginName = usernamePasswordToken.getUsername();
		AtomicInteger retryCount = loginRecordCache.get(loginName);
		if (retryCount == null)
        {
            retryCount = new AtomicInteger(0);
            loginRecordCache.put(loginName, retryCount);
        }
        if (retryCount.incrementAndGet() > Integer.valueOf(maxRetryCount).intValue())
        {
        	 log.warn("用户[{}]进行登录验证..失败验证超过{}次", loginName, maxRetryCount);
             throw new ExcessiveAttemptsException("username: " + loginName + " tried to login more than 5 times in period");  
        }
        SysUser user = userService.findByLoginName(loginName);
        if (!passwordService.matches(user, new String(usernamePasswordToken.getPassword())))
        {
            loginRecordCache.put(loginName, retryCount);
            throw new UserPasswordNotMatchException();
        }
        else
        {
        	passwordService.clearLoginRecordCache(loginName);
        }
		/*String password = new String(usernamePasswordToken.getPassword());        
		String dbPassword = (String) info.getCredentials();//数据库里的密码        
		return this.equals(password, dbPassword);   */
		return false;
	}
}

  

 成了


推荐阅读
  • 本文详细介绍了在PHP中如何获取和处理HTTP头部信息,包括通过cURL获取请求头信息、使用header函数发送响应头以及获取客户端HTTP头部的方法。同时,还探讨了PHP中$_SERVER变量的使用,以获取客户端和服务器的相关信息。 ... [详细]
  • 雨林木风 GHOST XP SP3 经典珍藏版 YN2014.04
    雨林木风 GHOST XP SP3 经典珍藏版 YN2014.04 ... [详细]
  • 本文探讨了在不同场景下如何高效且安全地存储Token,包括使用定时器刷新、数据库存储等方法,并针对个人开发者与第三方服务平台的不同需求提供了具体建议。 ... [详细]
  • 本文详细介绍了PHP中的几种超全局变量,包括$GLOBAL、$_SERVER、$_POST、$_GET等,并探讨了AJAX的工作原理及其优缺点。通过具体示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 本文详细介绍了如何使用Linux下的mysqlshow命令来查询MySQL数据库的相关信息,包括数据库、表以及字段的详情。通过本文的学习,读者可以掌握mysqlshow命令的基本语法及其常用选项。 ... [详细]
  • Java高级工程师学习路径及面试准备指南
    本文基于一位朋友的PDF面试经验整理,涵盖了Java高级工程师所需掌握的核心知识点,包括数据结构与算法、计算机网络、数据库、操作系统等多个方面,并提供了详细的参考资料和学习建议。 ... [详细]
  • 本文由chszs撰写,详细介绍了Apache Mina框架的核心开发流程及自定义协议处理方法。文章涵盖从创建IoService实例到协议编解码的具体步骤,适合希望深入了解Mina框架应用的开发者。 ... [详细]
  • 最适合初学者的编程语言
    本文探讨了适合编程新手的最佳语言选择,包括Python、JavaScript等易于上手且功能强大的语言,以及如何通过有效的学习方法提高编程技能。 ... [详细]
  • 搭建个人博客:WordPress安装详解
    计划建立个人博客来分享生活与工作的见解和经验,选择WordPress是因为它专为博客设计,功能强大且易于使用。 ... [详细]
  • 分布式计算助力链力实现毫秒级安全响应,确保100%数据准确性
    随着分布式计算技术的发展,其在数据存储、文件传输、在线视频、社交平台及去中心化金融等多个领域的应用日益广泛。国际知名企业如Firefox、Google、Opera、Netflix、OpenBazaar等均已采用该技术,推动了技术创新和服务升级。 ... [详细]
  • 宝塔面板下启用HTTPS的详细指南
    本文提供了在宝塔面板环境中配置HTTPS的具体步骤,确保您的网站通信更加安全可靠。 ... [详细]
  • 本文探讨了在使用 MyBatis 进行批量数据处理时遇到的参数绑定异常问题,并提供了详细的解决方案。 ... [详细]
  • 本文详细对比了HashMap和HashTable在多线程环境下的安全性、对null值的支持、性能表现以及方法同步等方面的特点,帮助开发者根据具体需求选择合适的数据结构。 ... [详细]
  • 2023年1月28日网络安全热点
    涵盖最新的网络安全动态,包括OpenSSH和WordPress的安全更新、VirtualBox提权漏洞、以及谷歌推出的新证书验证机制等内容。 ... [详细]
  • 本文探讨了使用Python实现监控信息收集的方法,涵盖从基础的日志记录到复杂的系统运维解决方案,旨在帮助开发者和运维人员提升工作效率。 ... [详细]
author-avatar
手机用户2702932507
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有