国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring Boot [集成-Shiro]

gclove / 1061人閱讀

摘要:后面的文章將圍繞著集成來進(jìn)行展開。表示當(dāng)前已經(jīng)身份驗(yàn)證或者通過記住我登錄的。表示當(dāng)前需要角色和。參考資料系列十五安全框架一基本功能權(quán)限管理學(xué)習(xí)資料使用手冊(cè)跟開濤學(xué)博客版跟開濤學(xué)版官方文檔

導(dǎo)讀:

在閱讀這篇文章之前假設(shè)你已經(jīng)對(duì)Apache Shiro(后面統(tǒng)一用Shiro作為代指)有了一定的了解,如果你還對(duì)Shiro不熟悉的話在這篇文章的結(jié)尾附有相關(guān)的學(xué)習(xí)資料,關(guān)于Shiro是用來做什么的這里有個(gè)不錯(cuò)的介紹,在后面的文章中就不在對(duì)其進(jìn)行描述了。后面的文章將圍繞著 Spring Boot 集成Shiro 來進(jìn)行展開。

快速上手: 1.引入pom依賴


    org.apache.shiro
    shiro-spring
    1.2.5
2.實(shí)現(xiàn)相關(guān)的 用戶,角色,權(quán)限等代碼的編寫:

由于篇幅原因這里不進(jìn)行展開 提供一個(gè)參考

3.實(shí)現(xiàn)Realm:

AbstractUserRealm繼承AuthorizingRealm,并重寫doGetAuthorizationInfo(用于獲取認(rèn)證成功后的角色、權(quán)限等信息) 和 doGetAuthenticationInfo(驗(yàn)證當(dāng)前登錄的Subject)方法:

public abstract class AbstractUserRealm extends AuthorizingRealm {

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

    @Autowired
    private UserRepository userRepository;
    //獲取用戶組的權(quán)限信息
    public abstract UserRolesAndPermissions doGetGroupAuthorizationInfo(User userInfo);
    //獲取用戶角色的權(quán)限信息
    public abstract UserRolesAndPermissions doGetRoleAuthorizationInfo(User userInfo);

    /**
     * 獲取授權(quán)信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String currentLoginName = (String) principals.getPrimaryPrincipal();
        Set userRoles = new HashSet<>();
        Set userPermissions = new HashSet<>();
        //從數(shù)據(jù)庫中獲取當(dāng)前登錄用戶的詳細(xì)信息
        User userInfo = userRepository.findByLoginName(currentLoginName);
        if (null != userInfo) {
            UserRolesAndPermissions groupContainer = doGetGroupAuthorizationInfo(userInfo);
            UserRolesAndPermissions roleContainer = doGetGroupAuthorizationInfo(userInfo);
            userRoles.addAll(groupContainer.getUserRoles());
            userRoles.addAll(roleContainer.getUserRoles());
            userPermissions.addAll(groupContainer.getUserPermissions());
            userPermissions.addAll(roleContainer.getUserPermissions());
        } else {
            throw new AuthorizationException();
        }
        //為當(dāng)前用戶設(shè)置角色和權(quán)限
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.addRoles(userRoles);
        authorizationInfo.addStringPermissions(userPermissions);
        logger.info("###【獲取角色成功】[SessionId] => {}", SecurityUtils.getSubject().getSession().getId());
        return authorizationInfo;
    }

    /**
     * 登錄認(rèn)證
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authenticationToken) throws AuthenticationException {
        //UsernamePasswordToken對(duì)象用來存放提交的登錄信息
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //查出是否有此用戶
        User user = userRepository.findByLoginName(token.getUsername());
        if (user != null) {
            // 若存在,將此用戶存放到登錄認(rèn)證info中,無需自己做密碼對(duì)比,Shiro會(huì)為我們進(jìn)行密碼對(duì)比校驗(yàn)
            return new SimpleAuthenticationInfo(user.getLoginName(), user.getPassword(), getName());
        }
        return null;
    }

    protected class UserRolesAndPermissions {
        Set userRoles;
        Set userPermissions;

        public UserRolesAndPermissions(Set userRoles, Set userPermissions) {
            this.userRoles = userRoles;
            this.userPermissions = userPermissions;
        }

        public Set getUserRoles() {
            return userRoles;
        }

        public Set getUserPermissions() {
            return userPermissions;
        }
    }
    
@Component
public class UserRealm extends AbstractUserRealm {

    @Override
    public UserRolesAndPermissions doGetGroupAuthorizationInfo(User userInfo) {
        Set userRoles = new HashSet<>();
        Set userPermissions = new HashSet<>();
        //TODO 獲取當(dāng)前用戶下?lián)碛械乃薪巧斜?及權(quán)限
        return new UserRolesAndPermissions(userRoles, userPermissions);
    }

    @Override
    public UserRolesAndPermissions doGetRoleAuthorizationInfo(User userInfo) {
        Set userRoles = new HashSet<>();
        Set userPermissions = new HashSet<>();
        //TODO 獲取當(dāng)前用戶下?lián)碛械乃薪巧斜?及權(quán)限
        return new UserRolesAndPermissions(userRoles, userPermissions);
    }
}
4.創(chuàng)建Shiro配置類:

這是最重要的一步等價(jià)于常規(guī)的Spring web應(yīng)用的配置文件,將相關(guān)的配置托管給Spring 管理。

@Configuration
public class ShiroConfiguration {

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

    /**
     * Shiro的Web過濾器Factory 命名:shiroFilter
* * @param securityManager * @return */ @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { logger.info("注入Shiro的Web過濾器-->shiroFilter", ShiroFilterFactoryBean.class); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //Shiro的核心安全接口,這個(gè)屬性是必須的 shiroFilterFactoryBean.setSecurityManager(securityManager); //要求登錄時(shí)的鏈接(可根據(jù)項(xiàng)目的URL進(jìn)行替換),非必須的屬性,默認(rèn)會(huì)自動(dòng)尋找Web工程根目錄下的"/login.jsp"頁面 shiroFilterFactoryBean.setLoginUrl("/login"); //登錄成功后要跳轉(zhuǎn)的連接,邏輯也可以自定義,例如返回上次請(qǐng)求的頁面 shiroFilterFactoryBean.setSuccessUrl("/index"); //用戶訪問未對(duì)其授權(quán)的資源時(shí),所顯示的連接 shiroFilterFactoryBean.setUnauthorizedUrl("/403"); /*定義shiro過濾器,例如實(shí)現(xiàn)自定義的FormAuthenticationFilter,需要繼承FormAuthenticationFilter **本例中暫不自定義實(shí)現(xiàn),在下一節(jié)實(shí)現(xiàn)驗(yàn)證碼的例子中體現(xiàn) */ /*定義shiro過濾鏈 Map結(jié)構(gòu) * Map中key(xml中是指value值)的第一個(gè)"/"代表的路徑是相對(duì)于HttpServletRequest.getContextPath()的值來的 * anon:它對(duì)應(yīng)的過濾器里面是空的,什么都沒做,這里.do和.jsp后面的*表示參數(shù),比方說login.jsp?main這種 * authc:該過濾器下的頁面必須驗(yàn)證后才能訪問,它是Shiro內(nèi)置的一個(gè)攔截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter */ Map filterChainDefinitionMap = new LinkedHashMap(); // 配置退出過濾器,其中的具體的退出代碼Shiro已經(jīng)替我們實(shí)現(xiàn)了 filterChainDefinitionMap.put("/logout", "logout"); // :這是一個(gè)坑呢,一不小心代碼就不好使了; // filterChainDefinitionMap.put("/login", "anon");//anon 可以理解為不攔截 filterChainDefinitionMap.put("/reg", "anon"); filterChainDefinitionMap.put("/plugins/**", "anon"); filterChainDefinitionMap.put("/pages/**", "anon"); filterChainDefinitionMap.put("/api/**", "anon"); filterChainDefinitionMap.put("/dists/img/*", "anon"); filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public EhCacheManager ehCacheManager() { EhCacheManager cacheManager = new EhCacheManager(); return cacheManager; } /** * 不指定名字的話,自動(dòng)創(chuàng)建一個(gè)方法名第一個(gè)字母小寫的bean * @Bean(name = "securityManager") * @return */ @Bean public SecurityManager securityManager(UserRealm userRealm) { logger.info("注入Shiro的Web過濾器-->securityManager", ShiroFilterFactoryBean.class); DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(userRealm); //注入緩存管理器; securityManager.setCacheManager(ehCacheManager());//這個(gè)如果執(zhí)行多次,也是同樣的一個(gè)對(duì)象; return securityManager; } /** * Shiro生命周期處理器 * @return */ @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * 開啟Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP掃描使用Shiro注解的類,并在必要時(shí)進(jìn)行安全邏輯驗(yàn)證 * 配置以下兩個(gè)bean(DefaultAdvisorAutoProxyCreator(可選)和AuthorizationAttributeSourceAdvisor)即可實(shí)現(xiàn)此功能 * @return */ @Bean @DependsOn({"lifecycleBeanPostProcessor"}) public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } }
5.實(shí)現(xiàn)登錄/退出等操作:
@Controller
public class SecurityController {

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

    @Autowired
    private UserService userService;

    @GetMapping("/login")
    public String loginForm() {
        return "login";
    }

    @PostMapping("/login")
    public String login(@Valid User user, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
        if (bindingResult.hasErrors()) {
            return "login";
        }
        String loginName = user.getLoginName();
        logger.info("準(zhǔn)備登陸用戶 => {}", loginName);
        UsernamePasswordToken token = new UsernamePasswordToken(loginName,user.getPassword());
        //獲取當(dāng)前的Subject
        Subject currentUser = SecurityUtils.getSubject();
        try {
            //在調(diào)用了login方法后,SecurityManager會(huì)收到AuthenticationToken,并將其發(fā)送給已配置的Realm執(zhí)行必須的認(rèn)證檢查
            //每個(gè)Realm都能在必要時(shí)對(duì)提交的AuthenticationTokens作出反應(yīng)
            //所以這一步在調(diào)用login(token)方法時(shí),它會(huì)走到MyRealm.doGetAuthenticationInfo()方法中,具體驗(yàn)證方式詳見此方法
            logger.info("對(duì)用戶[" + loginName + "]進(jìn)行登錄驗(yàn)證..驗(yàn)證開始");
            currentUser.login(token);
            logger.info("對(duì)用戶[" + loginName + "]進(jìn)行登錄驗(yàn)證..驗(yàn)證通過");
        } catch (UnknownAccountException uae) {
            logger.info("對(duì)用戶[" + loginName + "]進(jìn)行登錄驗(yàn)證..驗(yàn)證未通過,未知賬戶");
            redirectAttributes.addFlashAttribute("message", "未知賬戶");
        } catch (IncorrectCredentialsException ice) {
            logger.info("對(duì)用戶[" + loginName + "]進(jìn)行登錄驗(yàn)證..驗(yàn)證未通過,錯(cuò)誤的憑證");
            redirectAttributes.addFlashAttribute("message", "密碼不正確");
        } catch (LockedAccountException lae) {
            logger.info("對(duì)用戶[" + loginName + "]進(jìn)行登錄驗(yàn)證..驗(yàn)證未通過,賬戶已鎖定");
            redirectAttributes.addFlashAttribute("message", "賬戶已鎖定");
        } catch (ExcessiveAttemptsException eae) {
            logger.info("對(duì)用戶[" + loginName + "]進(jìn)行登錄驗(yàn)證..驗(yàn)證未通過,錯(cuò)誤次數(shù)過多");
            redirectAttributes.addFlashAttribute("message", "用戶名或密碼錯(cuò)誤次數(shù)過多");
        } catch (AuthenticationException ae) {
            //通過處理Shiro的運(yùn)行時(shí)AuthenticationException就可以控制用戶登錄失敗或密碼錯(cuò)誤時(shí)的情景
            logger.info("對(duì)用戶[" + loginName + "]進(jìn)行登錄驗(yàn)證..驗(yàn)證未通過,堆棧軌跡如下");
            ae.printStackTrace();
            redirectAttributes.addFlashAttribute("message", "用戶名或密碼不正確");
        }
        //驗(yàn)證是否登錄成功
        if (currentUser.isAuthenticated()) {
            logger.info("用戶[" + loginName + "]登錄認(rèn)證通過(這里可以進(jìn)行一些認(rèn)證通過后的一些系統(tǒng)參數(shù)初始化操作)");
            return "redirect:/index";
        } else {
            token.clear();
            return "redirect:/login";
        }
    }

    @GetMapping("/logout")
    public String logout(RedirectAttributes redirectAttributes) {
        //使用權(quán)限管理工具進(jìn)行用戶的退出,跳出登錄,給出提示信息
        SecurityUtils.getSubject().logout();
        redirectAttributes.addFlashAttribute("message", "您已安全退出");
        return "redirect:/login";
    }


    @GetMapping("/reg")
    @ResponseBody
    public Result reg(@Valid User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return Result.error("用戶信息填寫不完整");
        }
        userService.save(user);
        return Result.ok();
    }
}
6.前端頁面編寫:

一個(gè)簡單 form表單提交的demo

        
擴(kuò)展:

權(quán)限注解:

@RequiresAuthentication  
表示當(dāng)前Subject已經(jīng)通過login進(jìn)行了身份驗(yàn)證;即Subject. isAuthenticated()返回true。 

@RequiresUser  
表示當(dāng)前Subject已經(jīng)身份驗(yàn)證或者通過記住我登錄的。

@RequiresGuest  
表示當(dāng)前Subject沒有身份驗(yàn)證或通過記住我登錄過,即是游客身份。
  
@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)  
表示當(dāng)前Subject需要角色admin和user。

@RequiresPermissions (value={“user:a”, “user:b”}, logical= Logical.OR)  
表示當(dāng)前Subject需要權(quán)限user:a或user:b。  

標(biāo)簽
代碼驗(yàn)證:
(暫時(shí)忽略)留待補(bǔ)充

結(jié)語:

Shiro 作為一款安全框架為我們提供了常用的功能,已經(jīng)足夠應(yīng)對(duì)絕大多數(shù)的業(yè)務(wù)需要,在下一篇文章中將介紹一款更加強(qiáng)大的安全框架 Spring Security。

參考資料:

Spring Boot系列(十五) 安全框架Apache Shiro(一)基本功能
Spring Boot Shiro 權(quán)限管理

學(xué)習(xí)資料:

Apache Shiro 使用手冊(cè)
《跟開濤學(xué)Shiro》 - 博客版
跟開濤學(xué) Shiro - wiki版
官方文檔

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/11245.html

相關(guān)文章

  • Spring Boot [集成-Shiro]

    摘要:后面的文章將圍繞著集成來進(jìn)行展開。表示當(dāng)前已經(jīng)身份驗(yàn)證或者通過記住我登錄的。表示當(dāng)前需要角色和。參考資料系列十五安全框架一基本功能權(quán)限管理學(xué)習(xí)資料使用手冊(cè)跟開濤學(xué)博客版跟開濤學(xué)版官方文檔 導(dǎo)讀: 在閱讀這篇文章之前假設(shè)你已經(jīng)對(duì)Apache Shiro(后面統(tǒng)一用Shiro作為代指)有了一定的了解,如果你還對(duì)Shiro不熟悉的話在這篇文章的結(jié)尾附有相關(guān)的學(xué)習(xí)資料,關(guān)于Shiro是用來做什...

    superw 評(píng)論0 收藏0
  • 《 Kotlin + Spring Boot : 下一代 Java 服務(wù)端開發(fā) 》

    摘要:下一代服務(wù)端開發(fā)下一代服務(wù)端開發(fā)第部門快速開始第章快速開始環(huán)境準(zhǔn)備,,快速上手實(shí)現(xiàn)一個(gè)第章企業(yè)級(jí)服務(wù)開發(fā)從到語言的缺點(diǎn)發(fā)展歷程的缺點(diǎn)為什么是產(chǎn)生的背景解決了哪些問題為什么是的發(fā)展歷程容器的配置地獄是什么從到下一代企業(yè)級(jí)服務(wù)開發(fā)在移動(dòng)開發(fā)領(lǐng)域 《 Kotlin + Spring Boot : 下一代 Java 服務(wù)端開發(fā) 》 Kotlin + Spring Boot : 下一代 Java...

    springDevBird 評(píng)論0 收藏0
  • springmvc項(xiàng)目轉(zhuǎn)為springboot

    摘要:說明如果你的項(xiàng)目連項(xiàng)目都不是,請(qǐng)自行轉(zhuǎn)為項(xiàng)目,在按照本教程進(jìn)行。本教程適用于的項(xiàng)目。處理攔截資源文件問題。 說明 如果你的項(xiàng)目連maven項(xiàng)目都不是,請(qǐng)自行轉(zhuǎn)為maven項(xiàng)目,在按照本教程進(jìn)行。本教程適用于spring+springmvc+mybatis+shiro的maven項(xiàng)目。1.修改pom文件依賴 刪除之前的spring依賴,添加springboot依賴 or...

    wqj97 評(píng)論0 收藏0
  • Spring Security

    摘要:框架具有輕便,開源的優(yōu)點(diǎn),所以本譯見構(gòu)建用戶管理微服務(wù)五使用令牌和來實(shí)現(xiàn)身份驗(yàn)證往期譯見系列文章在賬號(hào)分享中持續(xù)連載,敬請(qǐng)查看在往期譯見系列的文章中,我們已經(jīng)建立了業(yè)務(wù)邏輯數(shù)據(jù)訪問層和前端控制器但是忽略了對(duì)身份進(jìn)行驗(yàn)證。 重拾后端之Spring Boot(四):使用JWT和Spring Security保護(hù)REST API 重拾后端之Spring Boot(一):REST API的搭建...

    keelii 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<