Springboot+Shiro+Mybatis 前後端分離

pom.xml

<!--shiro start-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>${shiro.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>${shiro.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-web</artifactId>
    <version>${shiro.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>${shiro.version}</version>
</dependency>
<dependency>
    <groupId>com.github.theborakompanioni</groupId>
    <artifactId>thymeleaf-extras-shiro</artifactId>
    <version>2.0.0</version>
</dependency>
<!--shiro end-->

MyExceptionHandler 統一異常處理, json格式

@ControllerAdvice
@Slf4j
public class MyExceptionHandler {

//    @ResponseBody
//    @ExceptionHandler(BizException.class)
    public ResData handleException(BizException e){
        ResData resData = new ResData();
        resData.setResInfo(false,e.getCode(), e.getMessage());
        return resData;
    }
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ResData handleException(Exception e){
        ResData resData = new ResData();
        resData.setResInfo(false,RespCode.RespEnum.PARAMETER_IS_WRONG.getCode(), RespCode.RespEnum.PARAMETER_IS_WRONG.getDescribe());
        return resData;
    }
    @ResponseBody
    @ExceptionHandler(AccountException.class)
    public ResData handlerUnauthorizedException(AccountException e) {
       log.debug("MyExceptionHandler.handlerUnauthorizedException 權限認證Exception{}");
        ResData resData = new ResData();
        resData.setResInfo(false,RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getCode(), RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getDescribe());
        return resData;
    }
    @ResponseBody
    @ExceptionHandler(AuthorizationException.class)
    public ResData handlerAuthorizationException(AuthorizationException e) {
        log.debug("MyExceptionHandler.handlerAuthorizationException{}");
        ResData resData = new ResData();
        resData.setResInfo(false,RespCode.RespEnum.SYSERROR_PERMISSIONS_403.getCode(), RespCode.RespEnum.SYSERROR_PERMISSIONS_403.getDescribe());
        return resData;
    }


}

CustomManagerMvcConfig 可以來擴展SpringMVC的功能,此處主要處理跨域問題

package com.yxds.manager.common.interceptor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;

//使用 WebMvcConfigurerAdapter 可以來擴展SpringMVC的功能
//WebMvcConfigurationSupport  會是靜態資源失效需要擴展
//@EnableWebMvc   不要接管SpringMVC
@Configuration
public class CustomManagerMvcConfig implements WebMvcConfigurer {

    //所有的WebMvcConfigurerAdapter組件都會一起起作用
    @Bean //將組件註冊在容器
    public WebMvcConfigurer webMvcConfigurer() {
        WebMvcConfigurer adapter = new WebMvcConfigurer() {

            @Override
            public void addViewControllers(ViewControllerRegistry registry) {
                //瀏覽器發送 /test 請求來到 success 添加視圖映射
                registry.addViewController("/").setViewName("login");
                registry.addViewController("/index.html").setViewName("login");
                //防止重複提交
                registry.addViewController("/home.html").setViewName("home");
//                registry.addViewController("/welcome.html").setViewName("welcome");
            }

            //註冊攔截器
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                //super.addInterceptors(registry);
                //靜態資源;  *.css , *.js
                //SpringBoot已經做好了靜態資源映射
                //免登陸
                if(false){
                registry.addInterceptor(new ManagerLoginHandlerInterceptor())
                        // 排除配置
                        .excludePathPatterns("/",
                                "/error",
                                "/static/**",
                                //排除訪問swagger
                                "/swagger-resources/**", "/v2/**", "/swagger-ui.html/**",
                                "/webjars/**",
                                "/index.html",
                                "/test/**",//過濾自檢代碼
                                "/sys/login",
                                "/sys/login/userMenuList",//userMenu
                                "/sys/logout",//退出
                                "/sys/Promote/SumKey/*"//首頁數據
                        )
                        // 攔截配置
                        .addPathPatterns("/**");
                }
            }

            @Override
            public void addResourceHandlers(ResourceHandlerRegistry registry) {
                registry.addResourceHandler("/static/**")
                        .addResourceLocations("classpath:/static/");
                registry.addResourceHandler("/templates/**")
                        .addResourceLocations("classpath:/templates/");
                //過濾swagger
                registry.addResourceHandler("swagger-ui.html")
                        .addResourceLocations("classpath:/META-INF/resources/");
                registry.addResourceHandler("/webjars/**")
                        .addResourceLocations("classpath:/META-INF/resources/webjars/");
                registry.addResourceHandler("/v2/api-docs/**")
                        .addResourceLocations("classpath:/META-INF/resources/v2/api-docs/");

                //super.addResourceHandlers(registry);

            }
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                WebMvcConfigurer.super.addCorsMappings(registry);
                registry.addMapping("/**")//需要跨域訪問的Map路徑
                        .allowedOrigins("*")//允許跨域訪問的ip及端口
                        .allowedHeaders("*")//允許跨域訪問的Headers內容
                        .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")//允許跨域訪問的方法,OPTIONS必須設置Shiro中用到
                        .allowCredentials(true);
            }

        };
        return adapter;
    }


//    以下WebMvcConfigurerAdapter 比較常用的重寫接口
//    /** 解決跨域問題 **/
//    public void addCorsMappings(CorsRegistry registry) ;
//    /** 添加攔截器 **/
//    void addInterceptors(InterceptorRegistry registry);
//    /** 這裏配置視圖解析器 **/
//    /** 視圖跳轉控制器 **/
//    void addViewControllers(ViewControllerRegistry registry);
//    void configureViewResolvers(ViewResolverRegistry registry);
//    /** 配置內容裁決的一些選項 **/
//    void configureContentNegotiation(ContentNegotiationConfigurer configurer);
//    /** 視圖跳轉控制器 **/
//    void addViewControllers(ViewControllerRegistry registry);
//    /** 靜態資源處理 **/
//    void addResourceHandlers(ResourceHandlerRegistry registry);
//    /** 默認靜態資源處理器 **/
//    void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer);

}

CORSAuthenticationFilter 自定義身份驗證過濾器

package com.yxds.manager.component.shiro;

import com.alibaba.fastjson.JSONObject;
import com.yxds.common.constants.Constants;
import com.yxds.common.constants.LocalSessionCache;
import com.yxds.common.exception.RespCode;
import com.yxds.common.protocol.respprotocol.ResData;
import com.yxds.common.utils.stringutil.StringUtil;
import com.yxds.dao.entity.sys.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@Slf4j
public class CORSAuthenticationFilter extends FormAuthenticationFilter {

    public CORSAuthenticationFilter() {
        super();
    }

        @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        //Always return true if the request's method is OPTIONS
        if (request instanceof HttpServletRequest) {
            if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
                return true;
            }
        }
        return super.isAccessAllowed(request, response, mappedValue);
    }


    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
            throws Exception
    {
//        String token = WebUtils.toHttp(request).getHeader(Constants.SysConstants.SYS_USER_TOKEN);
        if (isLoginRequest(request, response)) {
            if (isLoginSubmission(request, response)) {
                return executeLogin(request, response);
            } else {
                return true;
            }
//        }
//        SysUser user =(SysUser) LocalSessionCache.getSession(token);
//        if (StringUtil.isObjectNotEmpty(token)&&StringUtil.isObjectNotEmpty(user)&&token.trim().equals(user.getId().toString())) {
//            if (isLoginSubmission(request, response)) {
//                return executeLogin(request, response);
//            } else {
//                return true;
//            }
        }else {
            //解決 WebUtils.toHttp 往返回response寫數據跨域問題
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            String origin = httpRequest.getHeader("Origin");
            HttpServletResponse httpServletResponse = (HttpServletResponse) response;
            httpServletResponse.setHeader("Access-Control-Allow-Origin", origin);
            //通過對 Credentials 參數的設置,就可以保持跨域 Ajax 時的 Cookie
            //設置了Allow-Credentials,Allow-Origin就不能爲*,需要指明具體的url域
            httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
            // 返回固定的JSON串
            WebUtils.toHttp(response).setContentType("application/json; charset=utf-8");
            ResData resData = new ResData();
            resData.setResInfo(false, RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getCode(), RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getDescribe());
            WebUtils.toHttp(response).getWriter().print(JSONObject.toJSONString(resData));
            return false;
        }
    }
}

CustomSessionIdGenerator 自定義SessionId 生成器

package com.yxds.manager.component.shiro;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;

import java.io.Serializable;
import java.util.UUID;

public class CustomSessionIdGenerator implements SessionIdGenerator {
    @Override
    public Serializable generateId(Session session) {
        return "yx"+ UUID.randomUUID().toString().replace("-","");
    }
}

ShiroSessionManager 自定義Session 管理器

package com.yxds.manager.component.shiro;

import com.alibaba.fastjson.JSONObject;
import com.yxds.common.constants.Constants;
import com.yxds.common.constants.LocalSessionCache;
import com.yxds.common.exception.RespCode;
import com.yxds.common.protocol.respprotocol.ResData;
import com.yxds.common.utils.stringutil.StringUtil;
import com.yxds.service.shiro.ShiroUtilsManager;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;

public class ShiroSessionManager extends DefaultWebSessionManager {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
//    private static final String AUTHORIZATION = "Authorization";
    private static final String AUTHORIZATION = Constants.SysConstants.SYS_USER_TOKEN;
    private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";

    public ShiroSessionManager() {
        super();
    }

    @Override
    protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
        //前端ajax的headers中必須傳入Authorization的值
        String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
        Object sessionId = LocalSessionCache.getSession(id);

        if(StringUtil.isObjectNotEmpty(id)){
            Object o  = LocalSessionCache.getSession(id+sessionId);
            if(StringUtil.isObjectEmpty(o))
                return null;
        }

        //如果請求頭中有 Authorization 則其值爲sessionId
        if (!StringUtils.isEmpty(id)&& StringUtil.isObjectNotEmpty(sessionId)) {
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId.toString());
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
            logger.info("調用MySessionManager獲取sessionId=" + id);
            return sessionId.toString();
        } else {
            //否則按默認規則從cookie取sessionId
            logger.info("調用MySessionManager使用默認模式從cookie獲取sessionID爲" + id);
            return super.getSessionId(request, response);
        }
    }
}

UserShiroRealm 實現Realm

package com.yxds.manager.component.shiro;

import com.yxds.common.constants.Constants;
import com.yxds.dao.entity.sys.SysMenuButton;
import com.yxds.dao.entity.sys.SysUser;
import com.yxds.service.manager.sys.SysMenuButtonService;
import com.yxds.service.manager.sys.SysRoleMenuService;
import com.yxds.service.manager.sys.SysUserService;
import com.yxds.service.shiro.ShiroUtilsManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Arrays;
import java.util.List;


@Slf4j
public class UserShiroRealm extends AuthorizingRealm {
    @Autowired
    SysUserService sysUserService;
    @Autowired
    SysMenuButtonService sysMenuButtonService;
    @Autowired
    SysRoleMenuService sysRoleMenuService;

    /**
     * 身份認證
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.debug("UserShiroRealm.doGetAuthenticationInfo{}", Constants.SysConstants.SHOW_DEBUG_TAG);
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        SysUser hasSysUser = sysUserService.findByUserInfo(username);
        if (hasSysUser == null) {
            return null;
        }
        String loginPwd = hasSysUser.getLoginPwd();
        hasSysUser.setLoginPwd("");
        // 若存在,將此用戶存放到登錄認證info中,無需自己做密碼對比,Shiro會爲我們進行密碼對比校驗
        //此處沒有加鹽
        //hasSysUser 認證成功的返回信息
        SimpleAuthenticationInfo simpleAuthenticationInfo =
                new SimpleAuthenticationInfo(hasSysUser, loginPwd,ByteSource.Util.bytes(hasSysUser.getLoginName()), getName());
        return simpleAuthenticationInfo;
    }


    /**
     * 權限認證
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.debug("UserShiroRealm.doGetAuthorizationInfo{}", "執行Shiro權限認證"+Constants.SysConstants.SHOW_DEBUG_TAG);
        SysUser sysUser = (SysUser) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        if(ShiroUtilsManager.authcOpen){
            if (sysUser.getLoginName().equals(Constants.SysConstants.SYS_ADMIN_TYPE)) {
                authorizationInfo.addStringPermission("*:*:*");
            }else {
                if (sysUser != null) {
    //                List<SysMenuButton>  sysMenuButtonList = sysMenuButtonService.getUserSysMenuButtonList(sysUser.getId());
                    String butFlag = sysRoleMenuService.getUserSysMenuButtonFlag(sysUser.getId());
                    List<String> butFlagList = Arrays.asList(butFlag.split(","));
                    for (String f : butFlagList) {
                            authorizationInfo.addStringPermission(f);
                        }
                }
            }
        }else{
            authorizationInfo.addStringPermission("*:*:*");
        }
        return authorizationInfo;
    }

}

ShiroConfiguration

package com.yxds.manager.component.shiro;


import com.yxds.common.constants.Constants;
import com.yxds.service.shiro.ShiroUtilsManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

@Slf4j
@Configuration
public class ShiroConfiguration {

    @Bean(name = "shiroFilterFactoryBean")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        log.debug("ShiroConfiguration.shiroFilterFactoryBean{}", Constants.SysConstants.SHOW_DEBUG_TAG);

        Map<String, String> filterChainDefinitionManager = new LinkedHashMap<String, String>();

        filterChainDefinitionManager.put("/error", "anon");
        filterChainDefinitionManager.put("/static/**", "anon");
        //排除訪問swagger
        filterChainDefinitionManager.put( "/swagger-resources/**", "anon");
        filterChainDefinitionManager.put( "/v2/**", "anon");
        filterChainDefinitionManager.put( "/swagger-ui.html/**", "anon");

        filterChainDefinitionManager.put("/webjars/**", "anon");
        filterChainDefinitionManager.put("/index.html", "anon");
        filterChainDefinitionManager.put("/login.html", "anon");
        filterChainDefinitionManager.put("/sys/login", "anon");
        filterChainDefinitionManager.put("/sys/login/userMenuList", "anon");//userMenu
        filterChainDefinitionManager.put("/sys/logout", "anon");//退出
        filterChainDefinitionManager.put("/sys/Promote/SumKey/*", "anon");//首頁數據


        filterChainDefinitionManager.put("/**",  "user");// authc user 其他資源全部攔截.
        if(!ShiroUtilsManager.authcOpen)
        filterChainDefinitionManager.put("/**",  "anon");
//        shiroFilterFactoryBean.setLoginUrl("/unauth");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager);

        //自定義過濾器
        Map<String, Filter> filterMap = new LinkedHashMap<>();
        filterMap.put("user",new CORSAuthenticationFilter());
        shiroFilterFactoryBean.setFilters(filterMap);

        return shiroFilterFactoryBean;
    }


    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userShiroRealm());
        securityManager.setCacheManager(ehCacheManager());
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }


    @Bean
    public UserShiroRealm userShiroRealm() {
        UserShiroRealm userShiroRealm = new UserShiroRealm();
        //緩存開關 setCachingEnabled 管理 setAuthenticationCachingEnabled,setAuthorizationCachingEnabled
        userShiroRealm.setCachingEnabled(false);
        //啓用身份驗證緩存,即緩存AuthenticationInfo信息,默認false
//        userShiroRealm.setAuthenticationCachingEnabled(false);
        //緩存AuthenticationInfo信息的緩存名稱 在ehcache-shiro.xml中有對應緩存的配置
        userShiroRealm.setAuthenticationCacheName("authenticationCache");
        //啓用授權緩存,即緩存AuthorizationInfo信息,默認false
//        userShiroRealm.setAuthorizationCachingEnabled(false);
        //緩存AuthorizationInfo信息的緩存名稱  在ehcache-shiro.xml中有對應緩存的配置
        userShiroRealm.setAuthorizationCacheName("authorizationCache");
        userShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return userShiroRealm;
    }

    /**
     * 憑證匹配器
     * (由於我們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了
     *  所以我們需要修改下doGetAuthenticationInfo中的代碼;
     * )
     * @return
     */
   @Bean
   public HashedCredentialsMatcher hashedCredentialsMatcher(){
      HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
      hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:這裏使用MD5算法;
      hashedCredentialsMatcher.setHashIterations(2);//散列的次數,比如散列兩次,相當於 md5(md5(""));
      return hashedCredentialsMatcher;
   }

    @Bean(name = "ehCacheManager")
    @DependsOn("lifecycleBeanPostProcessor")
    public EhCacheManager ehCacheManager(){
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
        return ehCacheManager;
    }
    @Bean
    public SessionManager sessionManager() {
        ShiroSessionManager sessionManager =  new ShiroSessionManager();
        sessionManager.setSessionDAO(sessionDAO());
        sessionManager.setCacheManager(ehCacheManager());

        //全局會話超時時間(單位毫秒),默認30分鐘  暫時設置爲10秒鐘 用來測試
        sessionManager.setGlobalSessionTimeout(1800000);
//        sessionManager.setGlobalSessionTimeout(10000);
        //是否開啓刪除無效的session對象  默認爲true
        sessionManager.setDeleteInvalidSessions(true);
        //是否開啓定時調度器進行檢測過期session 默認爲true
//        sessionManager.setSessionValidationSchedulerEnabled(true);
        //設置session失效的掃描時間, 清理用戶直接關閉瀏覽器造成的孤立會話 默認爲 1個小時
        //設置該屬性 就不需要設置 ExecutorServiceSessionValidationScheduler 底層也是默認自動調用ExecutorServiceSessionValidationScheduler
        //暫時設置爲 5秒 用來測試
        sessionManager.setSessionValidationInterval(3600000);
//        sessionManager.setSessionValidationInterval(5000);

        //取消url 後面的 JSESSIONID
        sessionManager.setSessionIdUrlRewritingEnabled(false);

        return sessionManager;
    }

    @Bean
    public SessionDAO sessionDAO() {
        EnterpriseCacheSessionDAO enterpriseCacheSessionDAO = new EnterpriseCacheSessionDAO();
        //使用ehCacheManager
        enterpriseCacheSessionDAO.setCacheManager(ehCacheManager());
        //設置session緩存的名字 默認爲 shiro-activeSessionCache
        enterpriseCacheSessionDAO.setActiveSessionsCacheName("shiro-activeSessionCache");
        //sessionId生成器
        enterpriseCacheSessionDAO.setSessionIdGenerator(sessionIdGenerator());
        return enterpriseCacheSessionDAO;
    }

    @Bean
    public CustomSessionIdGenerator sessionIdGenerator() {
        return new CustomSessionIdGenerator();
    }

    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    /**
     *  開啓shiro aop註解支持.
     *  使用代理方式;所以需要開啓代碼支持;
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }


    ///附加功能///////////////////////////////

}

ehcache-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="es">
    <diskStore path="java.io.tmpdir"/>

    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="0"
            timeToLiveSeconds="0"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
    />

    <!-- 授權緩存 -->
    <cache name="authorizationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="0"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <!-- 認證緩存 -->
    <cache name="authenticationCache"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="0"
           timeToLiveSeconds="0"
           overflowToDisk="false"
           statistics="true">
    </cache>

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

</ehcache>

ShiroUtilsManager 用戶數據通過shiro獲取,獲取前判斷用戶的有效性

package com.yxds.service.shiro;


import com.yxds.common.constants.Constants;
import com.yxds.common.constants.LocalSessionCache;
import com.yxds.common.exception.BizException;
import com.yxds.common.exception.RespCode;
import com.yxds.common.utils.stringutil.StringUtil;
import com.yxds.dao.entity.sys.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
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.apache.shiro.util.ByteSource;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.http.HttpServletRequest;

@Slf4j
public class ShiroUtilsManager {

    public static String  defaultPwd = "123456";
    public static boolean authcOpen = true;

    public static Subject getSubject() {
        return SecurityUtils.getSubject();
    }

    public static Session getSession() {
        return SecurityUtils.getSubject().getSession();
    }

    public static void logout() {
        getSubject().logout();
    }


    public static void setSysUser(SysUser user) {
        Subject subject = getSubject();
        PrincipalCollection principalCollection = subject.getPrincipals();
        String realmName = principalCollection.getRealmNames().iterator().next();
        PrincipalCollection newPrincipalCollection = new SimplePrincipalCollection(user, realmName);
        // 重新加載Principal
        subject.runAs(newPrincipalCollection);
    }

    public static SysUser getSysUser() {
        SysUser user = (SysUser) getSubject().getPrincipal();
        return user;
    }

//    public static SysUser getSysUser(HttpServletRequest request) {
//        SysUser sysUser = (SysUser) LocalSessionCache.getSession(getToken(request));
//        if(StringUtil.isObjectNotEmpty(sysUser))
//            return  sysUser;
//        return null;
//    }

    public static String getToken(HttpServletRequest request) {
       String token =  WebUtils.toHttp(request).getHeader(Constants.SysConstants.SYS_USER_TOKEN);
       if(StringUtil.isObjectEmpty(token))
            throw new BizException(RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getCode(), RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getDescribe());
        return  token;
    }

    public static String getIp() {
        return getSubject().getSession().getHost();
    }

    public static String getSessionId() {
        return String.valueOf(getSubject().getSession().getId());
    }
    public static Integer getUserId() {
        Subject subject = getSubject();
        if(subject.isAuthenticated()||subject.isRemembered()){
            Long userId =getSysUser().getId().longValue();
            return userId.intValue() ;

        }else {
            if(authcOpen){
                throw new BizException(RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getCode(), RespCode.RespEnum.SYSERROR_PERMISSIONS_401.getDescribe());
            }
            return null;
        }
    }
    public static String getLoginName() {
        return getSysUser().getLoginName();
    }

    /**
     * 生成隨機鹽
     */
    public static String randomSalt() {
        // 一個Byte佔兩個字節,此處生成的3字節,字符串長度爲6
        SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
        String hex = secureRandom.nextBytes(3).toHex();
        return hex;
    }
    public static String getPassword(String name , Object password , String userSalt){
        String hashAlgorithmName = "MD5";
        Object salt = ByteSource.Util.bytes(name+userSalt);
        int hashIterations = 2;
        Object result = new SimpleHash(hashAlgorithmName, password, salt, hashIterations);
        return result.toString();
    }
    public static String getPassword(String name , Object password){
        String hashAlgorithmName = "MD5";
        Object salt = ByteSource.Util.bytes(name);
        int hashIterations = 2;
        Object result = new SimpleHash(hashAlgorithmName, password, salt, hashIterations);
        return result.toString();
    }


    public static void main(String[] args) {
        log.info("////////////////////////////////");
//        String randomSalt=ShiroUtilsManager.randomSalt();
//        log.info(randomSalt);
//       log.info(ShiroUtilsManager.getPassword("test",ShiroUtilsManager.defaultPwd,randomSalt));
        log.info(ShiroUtilsManager.getPassword("dbtest", ShiroUtilsManager.defaultPwd));


        log.info("////////////////////////////////");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章