springboot(2):整合shiro-ehcache与freemarker

源码地址 https://github.com/ostars/springboot-fast.git  分支:dev_shiro

项目结构

├── doc                                           // doc files.  
├── log                                           // log files.  
├── src/main
│   ├──java/org/ostars/springbootfast             // Specific code.  
│    ├──security                                   // shiro config
│    ├──├──GlobalExceptionHandler                  // 未授权进入403页面
│    ├──├──ShiroConfig                             // 注册和配置不需要shiro控制的资源和页面
│    ├──├──ShiroRealm                              // 验证和授权
│    ├──├──ShiroTagConfig                          // shiro标签
│   ├──resources
│    ├──ehcache
│    ├──├──ehcache.xml                             // 使用ehcache做二级缓存
├── src/test                                      // test.  
├── .gitignore                                    
├── LICENSE                
├── README.md   

ShiroConfig.java

package org.ostars.springbootfast.security;

import net.sf.ehcache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.io.ResourceUtils;
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.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * shiro config
 *
 * @author isaac
 * @date 2019/10/9
 */
@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setSuccessUrl("/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");

        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");

        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        return shiroFilterFactoryBean;
    }

    @Bean
    public ShiroRealm shiroRealm() {
        ShiroRealm shiroRealm = new ShiroRealm();
        shiroRealm.setCacheManager(cacheManager());
        return shiroRealm;
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm());
        securityManager.setCacheManager(cacheManager());
        securityManager.setRememberMeManager(cookieRememberMeManager());
        return securityManager;
    }

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

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor =
                new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public EhCacheManager cacheManager() {
        CacheManager cacheManager = CacheManager.getCacheManager("es");
        if (cacheManager == null) {

            try {
                cacheManager = CacheManager.create(ResourceUtils.getInputStreamForPath("classpath:ehcache/ehcache.xml"));
            } catch (IOException e) {
                throw new RuntimeException("initialize cacheManager failed");
            }
        }

        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManager(cacheManager);
        return ehCacheManager;
    }

    @Bean
    public SimpleCookie simpleCookie() {
        SimpleCookie simpleCookie = new SimpleCookie();
        simpleCookie.setHttpOnly(true);
        simpleCookie.setMaxAge(604800);
        simpleCookie.setName("standardManagement");
        return simpleCookie;
    }

    @Bean
    public CookieRememberMeManager cookieRememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        cookieRememberMeManager.setCookie(simpleCookie());
        return cookieRememberMeManager;
    }

}

ShiroRealm.java

package org.ostars.springbootfast.security;

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.ostars.springbootfast.enums.StatusEnum;
import org.ostars.springbootfast.model.base.SysUserModel;
import org.ostars.springbootfast.service.base.SysResourceService;
import org.ostars.springbootfast.service.base.SysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.util.List;

import static org.ostars.springbootfast.utils.GlobalConstant.ADMINORGID;
import static org.ostars.springbootfast.utils.GlobalConstant.ISADMIN;

/**
 * shiro realm
 *
 * @author isaac
 * @date 2019/10/9
 */
public class ShiroRealm extends AuthorizingRealm {

    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysResourceService sysResourceService;

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String loginName = authenticationToken.getPrincipal().toString();
        if (StringUtils.isEmpty(loginName)) {
            throw new AccountException("empty loginName");
        }
        List<SysUserModel> userModels = this.sysUserService.selectByModel(new SysUserModel(loginName));
        if (userModels.size() == 0) {
            throw new LockedAccountException("no account find");
        }

        if (userModels.size() > 1) {
            throw new LockedAccountException("duplicate account");
        }

        SysUserModel sysUserModel = userModels.get(0);
        if (StatusEnum.DISABLE.getValue().equals(sysUserModel.getStatus())) {
            throw new LockedAccountException("account locked");
        }

        if (ISADMIN.equals(sysUserModel.getAdminFlag())) {
            sysUserModel.setOrgId(ADMINORGID);
        }

        return new SimpleAuthenticationInfo(sysUserModel, sysUserModel.getPassword(), getName());
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SysUserModel sysUserModel = (SysUserModel) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if (ISADMIN.equals(sysUserModel)) {
            info.addStringPermission("*:*");
            return info;
        }

        List<String> permissionList = this.sysResourceService.selectResourceByUserId(sysUserModel.getId());
        info.addStringPermissions(permissionList);
        return info;
    }
}
ShiroConTagConfig.java

package org.ostars.springbootfast.security;

import com.jagregory.shiro.freemarker.ShiroTags;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;

import freemarker.template.Configuration;
import org.springframework.context.annotation.ComponentScan;

/**
 * shiro tag config
 *
 * @author isaac
 * @date 2019/10/9
 */
@ComponentScan
public class ShiroTagConfig implements InitializingBean {
    @Autowired
    private Configuration configuration;

    @Override
    public void afterPropertiesSet() {
        configuration.setSharedVariable("shiro", new ShiroTags());
    }
}
GlobalExceptionHandler.java
package org.ostars.springbootfast.security;

import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import javax.servlet.http.HttpServletRequest;

/**
 * global exception handler
 *
 * @author isaac
 * @date 2019/10/9
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(value = UnauthorizedException.class)
    public String defaultUnauthorizedExceptionHandler(HttpServletRequest request, Exception e) {
        return "403";
    }
}

LoginUtil.java

package org.ostars.springbootfast.utils;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.ostars.springbootfast.model.base.SysUserModel;


/**
 * login util
 *
 * @author isaac
 * @date 2019/10/10
 */
public class LoginUtil {
    public static SysUserModel getLoginUser() {
        Subject subject = SecurityUtils.getSubject();
        return (SysUserModel) subject.getPrincipals().getPrimaryPrincipal();
    }
}

ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        <persistence strategy="localTempSwap"/>
    </defaultCache>
</ehcache>

LoginController.java

package org.ostars.springbootfast.controller.base;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.ostars.springbootfast.utils.LoginUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * login controller
 *
 * @author isaac
 * @date 2019/10/9
 */
@RestController
public class LoginController {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @PostMapping("login")
    public Map<String, Object> login(String userName, String password, boolean remeberMe, HttpServletRequest request) {
        Map<String, Object> map = new HashMap<>();
        map.put("success", false);
        Subject currentUser = SecurityUtils.getSubject();
        password = new Md5Hash(password).toHex();

        UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
        token.setRememberMe(remeberMe);

        try {
            currentUser.login(token);
        } catch (UnknownAccountException uae) {
            logger.info(uae.getMessage());
            map.put("info", "您输入的用户名或密码错误!");
            return map;
        } catch (IncorrectCredentialsException ice) {
            logger.info(ice.getMessage());
            map.put("info", "您输入的用户名或密码错误!");
            return map;
        } catch (LockedAccountException lae) {
            logger.info(lae.getMessage());
            map.put("info", "此用户已经被锁定不能登录,请与管理员联系!");
            return map;
        } catch (DisabledAccountException lae) {
            logger.info(lae.getMessage());
            map.put("info", "此用户已经被禁用不能登录,请与管理员联系!");
            return map;
        } catch (ExcessiveAttemptsException eae) {
            logger.info(eae.getMessage());
            map.put("info", "您输入的错误次数过多!");
            return map;
        } catch (AuthenticationException ae) {
            logger.info(ae.getMessage());
            map.put("info", "您输入的用户名或密码错误!");
            return map;
        }

        map.put("success", currentUser.isAuthenticated());
        request.getSession().setAttribute("isAdmin", LoginUtil.getLoginUser().getAdminFlag());
        return map;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值