Springboot+Shiro+Mybatis+Thymeleaf

首先是pom.xml注入依賴包

        <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>

UserShiroRealm

public class UserShiroRealm extends AuthorizingRealm {
    @Autowired
    SysUserService sysUserService;
    @Autowired
    SysRoleService sysRoleService;
    @Autowired
    SysMenuService sysMenuService;

    /**
     * 身份認證
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.debug("UserShiroRealm.doGetAuthenticationInfo{}", Constants.SHOW_DEBUG_TAG);
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        log.info("驗證當前Subject時獲取到token爲:{}",token.toString());
        //查出是否有此用戶
        //獲取用戶的輸入的賬號
        String username = token.getUsername();
        //實際項目中,這裏可以根據實際情況做緩存,如果不做,Shiro自己也是有時間間隔機制,2分鐘內不會重複執行該方法
        SysUser hasSysUser = sysUserService.getUserByLoginAllInfo(username,null);
//        log.info("hasSysUser:{}",hasSysUser);
        if (hasSysUser == null) {
            ////沒有返回登錄用戶名對應的SimpleAuthenticationInfo對象時,就會在LoginController中拋出UnknownAccountException異常
            return null;
        }else {
    //            可放在doGetAuthorizationInfo中執行
            // 若存在,將此用戶存放到登錄認證info中,無需自己做密碼對比,Shiro會爲我們進行密碼對比校驗
//            List<URole> rlist = uRoleDao.findRoleByUid(hasUser.getId());//獲取用戶角色
//            List<UPermission> plist = uPermissionDao.findPermissionByUid(hasUser.getId());//獲取用戶權限
//            List<String> roleStrlist=new ArrayList<String>();////用戶的角色集合
//            List<String> perminsStrlist=new ArrayList<String>();//用戶的權限集合
//            for (URole role : rlist) {
//                roleStrlist.add(role.getName());
//            }
//            for (UPermission uPermission : plist) {
//                perminsStrlist.add(uPermission.getName());
//            }
//            hasUser.setRoleStrlist(roleStrlist);
//            hasUser.setPerminsStrlist(perminsStrlist);
        }

        ByteSource credentialsSalt = ByteSource.Util.bytes(hasSysUser.getLoginName()+hasSysUser.getSalt());

        String loginPwd = hasSysUser.getLoginPwd();
        hasSysUser.setLoginPwd("");
        // 若存在,將此用戶存放到登錄認證info中,無需自己做密碼對比,Shiro會爲我們進行密碼對比校驗
        //此處沒有加鹽
        //hasSysUser 認證成功的返回信息
        SimpleAuthenticationInfo simpleAuthenticationInfo =
                new SimpleAuthenticationInfo(hasSysUser, loginPwd,credentialsSalt, getName());
        return simpleAuthenticationInfo;
    }



    /**
     * 權限認證
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.debug("UserShiroRealm.doGetAuthorizationInfo{}", "執行Shiro權限認證"+Constants.SHOW_DEBUG_TAG);
        SysUser sysUser = (SysUser) principalCollection.getPrimaryPrincipal();

        //權限信息對象info,用來存放查出的用戶的所有的角色(role)及權限(permission)
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 管理員擁有所有權限
        if (sysUser.getUserType().equals(0)) {
//        if (false) {
            authorizationInfo.addStringPermission("*:*:*");
        }else {
            if (sysUser != null) {
                //獲取用戶角色
                List<SysRole> sysUserRoleList =  sysRoleService.getSysRoleInfoUserListForShiro(sysUser.getId());
                for (SysRole r : sysUserRoleList) {
                    authorizationInfo.addRole(r.getRoleKey());
                    //獲取用戶權限
                    List<SysMenu> sysUserRoleMenuList = sysMenuService.getSysMenuInfoRoleListForShiro(r.getId());
                    for (SysMenu m : sysUserRoleMenuList) {
                        authorizationInfo.addStringPermission(m.getPerms());
                    }
                }
            }
        }
        // 返回null的話,就會導致任何用戶訪問被攔截的請求時,都會自動跳轉到unauthorizedUrl指定的地址
        return authorizationInfo;
    }

    /**
     * 清理當前緩存權限
     */
    public void clearCachedAuthorizationInfo() {
        log.debug("UserShiroRealm.clearCachedAuthorizationInfo{}", "執行Shiro權限認證"+Constants.SHOW_DEBUG_TAG);
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }

    /**
     * 重寫方法,清除當前用戶的的 授權緩存
     * @param principals
     */
    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    /**
     * 重寫方法,清除當前用戶的 認證緩存
     * @param principals
     */
    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    /**
     * 自定義方法:清除所有 授權緩存
     */
    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    /**
     * 自定義方法:清除所有 認證緩存
     */
    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }
    /**
     * 自定義方法:清除所有的  認證緩存  和 授權緩存
     */
    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }
}

ShiroConfiguration

@Configuration
public class ShiroConfiguration {

    /**
     * ShiroFilterFactoryBean 處理攔截資源文件問題。
     * 注意:單獨一個ShiroFilterFactoryBean配置是或報錯的,以爲在
     * 初始化ShiroFilterFactoryBean的時候需要注入:SecurityManager
     *
     * Filter Chain定義說明 1、一個URL可以配置多個Filter,使用逗號分隔 2、當設置多個過濾器時,全部驗證通過,才視爲通過
     * 3、部分過濾器可指定參數,如perms,roles
     *
     */


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

        // 過濾鏈定義,從上向下順序執行,一般將 /**放在最爲下邊
        Map<String, String> filterChainDefinitionManager = new LinkedHashMap<String, String>();

        // authc:所有url都必須認證通過纔可以訪問; anon:所有url都都可以匿名訪問
        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/getCaptcha", "anon");

        filterChainDefinitionManager.put("/sys/login", "anon");
        // 配置退出過濾器,其中的具體的退出代碼Shiro已經替我們實現了
//        filterChainDefinitionManager.put("/sys/loginOut", "authc");
//        filterChainDefinitionManager.put("/sys/**", "authc");
//        filterChainDefinitionManager.put("/**",  "authc");//其他資源全部攔截,必須通過身份認證成功可通過
        filterChainDefinitionManager.put("/**",  "user");//其他資源全部攔截.身份認證成功或通過記住我均可通過


        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager);

        // 如果不設置默認會自動尋找Web工程根目錄下的"/login.jsp"頁面
        shiroFilterFactoryBean.setLoginUrl("/login.html");
        // 登錄成功後要跳轉的鏈接
//        shiroFilterFactoryBean.setSuccessUrl("/home.html");
        // 未授權界面
//        shiroFilterFactoryBean.setUnauthorizedUrl("/403");

        return shiroFilterFactoryBean;
    }

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //設置realm
        securityManager.setRealm(userShiroRealm());
        //用戶授權/認證信息Cache, 採用EhCache 緩存  注入緩存管理器;
        securityManager.setCacheManager(ehCacheManager());//這個如果執行多次,也是同樣的一個對象;
        securityManager.setRememberMeManager(rememberMeManager());
        //配置自定義session管理,使用ehcache 或redis
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    //身份認證與權限認證
    @Bean(name = "userShiroRealm")
    @DependsOn("lifecycleBeanPostProcessor")
    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;
    }

    /**
     * cookie對象;
     * @return
     */
    @Bean
    public SimpleCookie rememberMeCookie(){
        log.debug("ShiroConfiguration.rememberMeCookie()");
        //這個參數是cookie的名稱,對應前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //如果httyOnly設置爲true,則客戶端不會暴露給客戶端腳本代碼,使用HttpOnly cookie有助於減少某些類型的跨站點腳本攻擊;
//        simpleCookie.setHttpOnly(true);
        //<!-- 記住我cookie生效時間30天 ,單位秒;-->
        simpleCookie.setMaxAge(259200);
        //simpleCookie.setMaxAge(20);
        return simpleCookie;
    }

    /**
     * cookie管理對象;
     * @return
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        log.debug("ShiroConfiguration.rememberMeManager()");
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        //rememberme cookie加密的密鑰 建議每個項目都不一樣 默認AES算法 密鑰長度(128 256 512 位),通過以下代碼可以獲取
        //KeyGenerator keygen = KeyGenerator.getInstance("AES");
        //SecretKey deskey = keygen.generateKey();
        //System.out.println(Base64.encodeToString(deskey.getEncoded()));
        byte[] cipherKey = Base64.decode("wGiHplamyXlVB11UXWol8g==");
        cookieRememberMeManager.setCipherKey(cipherKey);
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return cookieRememberMeManager;
    }



    @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;
    }

    /**
     * 添加ShiroDialect 爲了在thymeleaf裏使用shiro的標籤的bean
     * @return
     */
    @Bean(name = "shiroDialect")
    public ShiroDialect shiroDialect(){
        return new ShiroDialect();
    }



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

    /**
     * 配置session監聽
     * @return
     */
    @Bean("sessionListener")
    public ShiroSessionListener sessionListener(){
        ShiroSessionListener sessionListener = new ShiroSessionListener();
        return sessionListener;
    }

    /**
     * 配置會話ID生成器
     * @return
     */
    @Bean
    public SessionIdGenerator sessionIdGenerator() {
        return new JavaUuidSessionIdGenerator();
    }

    /**
     * SessionDAO的作用是爲Session提供CRUD並進行持久化的一個shiro組件
     * MemorySessionDAO 直接在內存中進行會話維護
     * EnterpriseCacheSessionDAO  提供了緩存功能的會話維護,默認情況下使用MapCache實現,內部使用ConcurrentHashMap保存緩存的會話。
     * @return
     */
    @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;
    }

    /**
     * 配置保存sessionId的cookie
     * 注意:這裏的cookie 不是上面的記住我 cookie 記住我需要一個cookie session管理 也需要自己的cookie
     * @return
     */
    @Bean("sessionIdCookie")
    public SimpleCookie sessionIdCookie(){
        //這個參數是cookie的名稱
        SimpleCookie simpleCookie = new SimpleCookie("tank-sys");
        //setcookie的httponly屬性如果設爲true的話,會增加對xss防護的安全係數。它有以下特點:

        //setcookie()的第七個參數
        //設爲true後,只能通過http訪問,javascript無法訪問
        //防止xss讀取cookie
        simpleCookie.setHttpOnly(true);
        simpleCookie.setPath("/");
        //maxAge=-1表示瀏覽器關閉時失效此Cookie
        simpleCookie.setMaxAge(-1);
        return simpleCookie;
    }

    /**
     * 配置會話管理器,設定會話超時及保存
     * @return
     */
    @Bean("sessionManager")
    public SessionManager sessionManager() {

        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        Collection<SessionListener> listeners = new ArrayList<SessionListener>();
        //配置監聽
        listeners.add(sessionListener());
        sessionManager.setSessionListeners(listeners);
        sessionManager.setSessionIdCookie(sessionIdCookie());
        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;

    }

}

ShiroSessionListener

public class ShiroSessionListener  implements SessionListener {
    /**
     * 統計在線人數
     * juc包下線程安全自增
     */
    private final AtomicInteger sessionCount = new AtomicInteger(0);

    /**
     * 會話創建時觸發
     * @param session
     */
    @Override
    public void onStart(Session session) {
        //會話創建,在線人數加一
        sessionCount.incrementAndGet();
    }

    /**
     * 退出會話時觸發
     * @param session
     */
    @Override
    public void onStop(Session session) {
        //會話退出,在線人數減一
        sessionCount.decrementAndGet();
    }

    /**
     * 會話過期時觸發
     * @param session
     */
    @Override
    public void onExpiration(Session session) {
        //會話過期,在線人數減一
        sessionCount.decrementAndGet();
    }
    /**
     * 獲取在線人數使用
     * @return
     */
    public AtomicInteger getSessionCount() {
        return sessionCount;
    }
}

ShiroUtils

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

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

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

    public static SysUser getSysUser() {
        SysUser user = (SysUser) getSubject().getPrincipal();
        /*if (obj != null) {
            user = new SysUser();
            BeanUtils.copyProperties(user, obj);
        }*/
        return user;
    }

    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 void clearCachedAuthorizationInfo() {
        RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
        UserShiroRealm realm = (UserShiroRealm) rsm.getRealms().iterator().next();
        realm.clearCachedAuthorizationInfo();
    }

    public static Long getUserId() {
        Long userId =null;
        Subject subject = getSubject();
        if(subject.isAuthenticated()||subject.isRemembered())
            userId=getSysUser().getId().longValue();
        return  userId;
    }

    public static String getLoginName() {
        return getSysUser().getLoginName();
    }

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

    public static String getSessionId() {
        return String.valueOf(getSubject().getSession().getId());
    }

    /**
     * 生成隨機鹽
     */
    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();
    }

ehcache-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="es">

    <!--
        緩存對象存放路徑
        java.io.tmpdir:默認的臨時文件存放路徑。
        user.home:用戶的主目錄。
        user.dir:用戶的當前工作目錄,即當前程序所對應的工作路徑。
        其它通過命令行指定的系統屬性,如“java –DdiskStore.path=D:\\abc ……”。
    -->
    <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>

SysLoginController

    @RequestMapping("/login")
    public String login(String loginName, String loginPwd, String captchaCode, boolean rememberMe , HttpServletRequest req, Model model)
    {

        try {
            if(StringUtil.isObjectEmpty(loginName)||StringUtil.isObjectEmpty(loginPwd)){
                model.addAttribute("message", RespCode.RespEnum.SYSUSER_LOGIN_20004.getDescribe());
                return  "login";
            }
            //從session中獲取隨機數
            String inputStr = captchaCode;
            String random = (String) req.getSession().getAttribute(RandomValidateCodeUtil.RANDOMCODEKEY);
//            if(!captchaCode.equals(random)){//登錄麻煩暫去除
            if(false){
                model.addAttribute("message", RespCode.RespEnum.SYSUSER_LOGIN_20005.getDescribe());
                return  "login";
            }
            // 把用戶名和密碼封裝爲 UsernamePasswordToken 對象   rememberme   token.setRememberMe(true);
            UsernamePasswordToken token = new UsernamePasswordToken(loginName, loginPwd, rememberMe);
            Subject currentUser = ShiroUtils.getSubject();
            log.info("對用戶:{},進行登錄驗證..驗證開始",loginName);

            currentUser.login(token);

            //驗證是否登錄成功
            if (currentUser.isAuthenticated()) {
                log.info("用戶:[{}]登錄認證通過(這裏可以進行一些認證通過後的一些系統參數初始化操作)",loginName);
//                req.getSession().setAttribute(PermissionsConstants.SYSUSER_CONSTANTS.SYS_USER_SESSION,ShiroUtils.getSysUser());
                return "redirect:/sys/home";
            } else {
                token.clear();
                log.info("用戶:[{}]登錄認證失敗,重新登陸",loginName);
                return "login";
            }

        } catch ( UnknownAccountException uae ) {
            log.info("對用戶:[{}]進行登錄驗證..驗證失敗-username wasn't in the system",loginName);
        } catch ( IncorrectCredentialsException ice ) {
            log.info("對用戶:[{}]進行登錄驗證..驗證失敗-password didn't match",loginName);
        } catch ( LockedAccountException lae ) {
            log.info("對用戶:[{}]進行登錄驗證..驗證失敗-account is locked in the system",loginName);
        } catch ( AuthenticationException ae ) {
            log.info("對用戶:[{}]進行登錄驗證..驗證失敗-password in the system",loginName);
        }catch (Exception e){
            log.info("對用戶:[{}]進行登錄驗證..驗證失敗-system",loginName);
            e.printStackTrace();
        }
        model.addAttribute("message", RespCode.RespEnum.SYSUSER_LOGIN_20006.getDescribe());
        return "login";
    }
    @PostMapping("/loginOut")
    @ResponseBody
    public RespData loginOut(HttpServletRequest req)
    {
        RespData respData = new RespData();
        try
        {
            ShiroUtils.logout();
            if(StringUtil.isObjectNotEmpty(ShiroUtils.getSysUser()))
                respData.setRespInfo(false,RespCode.RespEnum.FAIL.getCode(), RespCode.RespEnum.FAIL.getDescribe());
            respData.setRespInfo(true,RespCode.RespEnum.SUCCESS.getCode(), RespCode.RespEnum.SUCCESS.getDescribe());
        }
        catch (Exception e)
        {
            respData.setRespInfo(false,RespCode.RespEnum.FAIL.getCode(), RespCode.RespEnum.FAIL.getDescribe());
            e.printStackTrace();
        }
        return respData;
    }

權限控制

    /**
     * 用戶列表
     * @param model
     * @return
     */
    @RequiresPermissions("1026902")
    @GetMapping("/index")
    public String index(Model model)
    {
        model.addAttribute("sysStatus_List",PermissionsConstants.SYSSTATUS_MAP());
        return "sys/user/user-index";
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章