springboot整合shiro篇1--配置shiro

1:引入spring-shiro 依賴

        <!--權限攔截-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>

2:配置shiro的生命週期和切面攔截

@Configuration
@Slf4j
public class ShiroHelperConfig {


    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        log.info("lifecycleBeanPostProcessor bean");
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        log.info("lifecycleBeanPostProcessor bean");
        return creator;
    }
}

3:配置shiro的安全管理器

/**
 * shiro configuration
 **/
@Configuration
@Slf4j
@AutoConfigureAfter(value = {ShiroHelperConfig.class})
public class ShiroConfig {


    @Bean(name = "securityManager")
    public SecurityManager securityManager(@Qualifier("authRealm") TourismAuthorizingRealm authRealm,
                                           @Qualifier("cookieRememberMeManager") CookieRememberMeManager cookieRememberMeManager) {
        log.info("securityManager()");
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();


        // 設置rememberMe管理器
        securityManager.setRememberMeManager(cookieRememberMeManager);

        // 設置realm,解決doGetAuthorizationInfo方法沒有調用問題
        securityManager.setRealm(authRealm);

        return securityManager;
    }

    /**
     * realm
     *
     * @return
     */
    @Bean(name = "authRealm")
    public TourismAuthorizingRealm tourismAuthorizingRealm(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher matcher) {
        log.info("tourismAuthorizingRealm bean");
        TourismAuthorizingRealm myAuthorizingRealm = new TourismAuthorizingRealm();
        // 設置密碼憑證匹配器
        myAuthorizingRealm.setCredentialsMatcher(matcher);
        return myAuthorizingRealm;
    }


    /**
     * cookie對象;
     *
     * @return
     */
    public SimpleCookie rememberMeCookie() {
        // 這個參數是cookie的名稱,對應前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //記住我cookie生效時間30天(259200)單位秒;
        simpleCookie.setMaxAge(259200);
        return simpleCookie;
    }

    /**
     * 記住我管理器 cookie管理對象;
     */
    @Bean(name = "cookieRememberMeManager")
    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        return cookieRememberMeManager;
    }

    /**
     * 密碼匹配憑證管理器
     *
     * @return
     */
    @Bean(name = "hashedCredentialsMatcher")
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName(PasswordUtils.ALGORITHM_NAME);
        hashedCredentialsMatcher.setHashIterations(PasswordUtils.HASH_ITERATIONS);// 散列的次數,比如散列兩次,相當於
        return hashedCredentialsMatcher;
    }


    /**
     * 開啓shiro aop註解支持.
     * <p>
     * 使用代理方式;所以需要開啓代碼支持;
     * Controller才能使用@RequiresPermissions
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
            @Qualifier("securityManager") SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必須設置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        return shiroFilterFactoryBean;
    }



4:配置shiro的校驗器

public class TourismAuthorizingRealm extends AuthorizingRealm {

    private final static Logger logger = LoggerFactory.getLogger(TourismAuthorizingRealm.class);

    @Autowired
    @Qualifier("userService")
    private UserService userService;

    //shiro的權限配置方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        logger.info("權限配置-->doGetAuthorizationInfo");


        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        logger.info("----------------------------->" + principals.getPrimaryPrincipal());

        User user = (User) principals.getPrimaryPrincipal();
        logger.info("doGetAuthorizationInfo() user: {}", user);
        List<Role> roles = userService.getRoles(user.getUserId());
        for (Role role : roles) {

            authorizationInfo.addRole(role.getRoleName());

            // 如果有權限,應該增加所有角色對應的權限
            // authorizationInfo.addStringPermission()
        }

        logger.info("用戶: {},具有的角色: {}", user.getUserName(), authorizationInfo.getRoles());
        logger.info("用戶: {},具有的權限: {}", user.getUserName(), authorizationInfo.getStringPermissions());

        return authorizationInfo;
    }

    //shiro的身份驗證方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        logger.info("正在驗證身份...");
        SimpleAuthenticationInfo info = null;

        //將token轉換成UsernamePasswordToken
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        //從轉換後的token中獲取用戶名
        String username = upToken.getUsername();
        //查詢數據庫,得到用戶
        User user = userService.getOne(new QueryWrapper<User>().lambda().eq(User::getUserName, username));
        if (user == null) {
            logger.info("沒有用戶: {}", username);
            return null;
        }

        //得到加密密碼的鹽值
        ByteSource salt = ByteSource.Util.bytes(user.getUserSalt());

        logger.info("加密密碼的鹽: {}", salt);
        //得到鹽值加密後的密碼: 只用於方便數據庫測試,後期不會用到。
        Object md = new SimpleHash(PasswordUtils.ALGORITHM_NAME, upToken.getPassword(), salt, PasswordUtils.HASH_ITERATIONS);
        logger.info("鹽值加密後的密碼: {}", md);
        //TODO: 用戶名;用戶密碼;加密鹽;realm name
        info = new SimpleAuthenticationInfo(user, user.getUserPassword(), salt, getName());
        return info;
    }


5:配置用戶的加密方式

/**
 * password utils
 **/
public class PasswordUtils {

    public static final String ALGORITHM_NAME = "MD5";

    public static final int HASH_ITERATIONS = 1024;

    /**
     * 重新計算md5值
     *
     * @param password
     * @param salt
     * @return
     */
    public static String renewPassword(String password, String salt) {
        SimpleHash md5hash = new SimpleHash(
                ALGORITHM_NAME, password, salt, HASH_ITERATIONS);
        return md5hash.toHex();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章