基于springboot實(shí)現(xiàn)整合shiro實(shí)現(xiàn)登錄認(rèn)證以及授權(quán)過程解析
這篇文章主要介紹了基于springboot實(shí)現(xiàn)整合shiro實(shí)現(xiàn)登錄認(rèn)證以及授權(quán)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
1.添加shiro的依賴
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web- starter</artifactId> <version>1.4.0</version> </dependency>
2.先創(chuàng)建一個Realm
public class MyShiroRealm extends AuthorizingRealm { @Autowired private RoleService roleService;//角色模模塊 @Autowired private UserService userService;//用戶模塊 @Autowired private PermissionService permissionService;//權(quán)限模塊 /** * 用戶身份識別(登錄") * @param authenticationToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken authToken = (UsernamePasswordToken) authenticationToken; // 獲取用戶輸入的賬號 String userName = authToken.getUsername(); //通過賬號查找用戶信息 User user= userService.selectUserOne(userName);// 將賬戶名,密碼,鹽值,getName()實(shí)例化到SimpleAuthenticationInfo中交給Shiro來管理 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( user, user.getPassWord(), //這里是設(shè)置的密碼鹽 ByteSource.Util.bytes(user.getSalt()), getName()); return authenticationInfo; } /** * 訪問控制。比如某個用戶是否具有某個操作的使用權(quán)限 * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); String userName = (String) principalCollection.getPrimaryPrincipal(); if (userName == null) { log.error("授權(quán)失敗,用戶信息為空?。。?); return null; } try { //獲取用戶角色集 Set<String> listRole= roleService.findRoleByUsername(userName); simpleAuthorizationInfo.addRoles(listRole); //通過角色獲取權(quán)限集 for (String role : listRole) { Set<String> permission= permissionService.findPermissionByRole(role); simpleAuthorizationInfo.addStringPermissions(permission); } return simpleAuthorizationInfo; } catch (Exception e) { log.error("授權(quán)失敗,請檢查系統(tǒng)內(nèi)部錯誤!!!", e); } return simpleAuthorizationInfo; } }
3.創(chuàng)建shiro的配置類
@Configuration public class ShiroConfiguration { //配置自定義的Realm @Bean public MyShiroRealm myShiroRealm(HashedCredentialsMatcher matcher){ MyShiroRealm myShiroRealm= new MyShiroRealm(); //在這里配置密碼加密 myShiroRealm.setCredentialsMatcher(matcher); return myShiroRealm; } //將Realm注冊到securityManager中 @Bean public DefaultWebSecurityManager securityManager(HashedCredentialsMatcher matcher){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm(matcher)); return securityManager; } //如果沒有此name,將會找不到shiroFilter的Bean @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login"); //表示指定登錄頁面 shiroFilterFactoryBean.setSuccessUrl("/user/list"); // 登錄成功后要跳轉(zhuǎn)的鏈接 shiroFilterFactoryBean.setUnauthorizedUrl("/403"); //未授權(quán)頁面 Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();//攔截器, 配置不會被攔截的鏈接 順序判斷 filterChainDefinitionMap.put("/login","anon"); //所有匿名用戶均可訪問到Controller層的該方法下 filterChainDefinitionMap.put("/userLogin","anon"); filterChainDefinitionMap.put("/image/**","anon"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/fonts/**","anon"); filterChainDefinitionMap.put("/js/**","anon"); filterChainDefinitionMap.put("/logout","logout"); filterChainDefinitionMap.put("/**", "authc"); //authc:所有url都必須認(rèn)證通過才可以訪問; anon:所有url都都可以匿名訪問 //filterChainDefinitionMap.put("/**", "user"); //user表示配置記住我或認(rèn)證通過可以訪問的地址 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } /** * SpringShiroFilter首先注冊到spring容器 * 然后被包裝成FilterRegistrationBean * 最后通過FilterRegistrationBean注冊到servlet容器 * @return */ @Bean public FilterRegistrationBean delegatingFilterProxy(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); DelegatingFilterProxy proxy = new DelegatingFilterProxy(); proxy.setTargetFilterLifecycle(true); proxy.setTargetBeanName("shiroFilter"); filterRegistrationBean.setFilter(proxy); return filterRegistrationBean; } //設(shè)置cookie @Bean public SimpleCookie rememberMeCookie(){ //這個參數(shù)是cookie的名稱,對應(yīng)前端的checkbox的name=rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); //記住我cookie生效時(shí)間3個小時(shí)(單位秒) simpleCookie.setMaxAge(10800); return simpleCookie; } //cookie管理對象,記住我功能 @Bean 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("MD5"); hashedCredentialsMatcher.setHashIterations(1024);// 設(shè)置加密次數(shù) return hashedCredentialsMatcher; } //如果沒有這兩個配置,可能會授權(quán)失敗,所以依賴中還需要配置aop的依賴 @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(HashedCredentialsMatcher matcher) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager(matcher)); return authorizationAttributeSourceAdvisor; } @Bean @ConditionalOnMissingBean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; } }
4.新建controller并寫個登錄的方法
/** * 登錄頁面 這里對應(yīng)shiro中配置的shiroFilter的登錄方法 * @return */ @GetMapping("/login") public String login() { return "user/login"; }
//登錄方法 @PostMapping("/userLogin") public String toLogin( String userName,String passWord,Model model){ UsernamePasswordToken token =new UsernamePasswordToken(userName,passWord); Subject subject = SecurityUtils.getSubject(); try { //這里直接使用shiro的登錄方法 subject.login(token); return "redirect:user/list"; //登錄失敗時(shí),會catch到你的異常,異常通過全局處理 } catch (UnknownAccountException e) { model.addAttribute("msg","該賬號不存在"); } catch (IncorrectCredentialsException e) { model.addAttribute("msg","密碼錯誤,請重試"); } catch (LockedAccountException e) { model.addAttribute("msg","該賬戶已被鎖定,請聯(lián)系管理員"); } catch (Exception e) { model.addAttribute("msg","登錄失敗"); } return "user/login"; } //添加 @RequestMapping("/insertUser") @ResponseBody public int insertUser(User user){ //將uuid設(shè)置為密碼鹽值 String salt = UUID.randomUUID().toString().replaceAll("-",""); SimpleHash simpleHash = new SimpleHash("MD5", user.getPassWord(), salt, 1024); //添加用戶信息 user.setPassWord(simpleHash.toHex()).setValid(1).setSalt(salt).setCreateTime(new Date()).setDel(0); return userMapper.insertSelective(user); }
5.創(chuàng)建全局異常處理類
@RestControllerAdvice public class GlobalExceptionHandle { @ExceptionHandler(ShiroException.class) public String doHandleShiroException(ShiroException se,Model model) { se.printStackTrace(); if(se instanceof UnknownAccountException) return "賬戶不存在!"; else if(se instanceof LockedAccountException) return "賬戶已鎖定,請聯(lián)系管理員"; else if(se instanceof IncorrectCredentialsException) return "密碼錯誤,請重試"; else if(se instanceof AuthorizationException) return "沒有相應(yīng)權(quán)限,請聯(lián)系管理員"; else return "登錄失敗"; } }
權(quán)限需要開啟權(quán)限注解才生效
@GetMapping("/userPageList") @ResponseBody @RequiresPermissions("user:view") //這里是用戶對應(yīng)的權(quán)限 public PageList listPage(HttpServletRequest request){ PageList pageList = new PageList(); List<User> list= userService.findAllPage(request);//查詢出的條數(shù) int totalCount = userService.countAll();//總記錄數(shù) pageList.setRows(list); pageList.setTotal(totalCount); return pageList; }
shiro用戶角色和權(quán)限表
-- Table structure for `sys_permission` DROP TABLE IF EXISTS `sys_permission`; CREATE TABLE `sys_permission` ( `id` int(64) NOT NULL AUTO_INCREMENT, `name` varchar(32) DEFAULT NULL, `permission` varchar(32) DEFAULT NULL, `url` varchar(64) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of sys_permission -- ---------------------------- INSERT INTO `sys_permission` VALUES ('1', '用戶管理', 'user:view', 'user/userPageList'); INSERT INTO `sys_permission` VALUES ('2', '用戶添加', 'user:add', 'user/saveUser'); INSERT INTO `sys_permission` VALUES ('3', '用戶刪除', 'user:del', 'user/delById'); -- ---------------------------- -- Table structure for `sys_role` -- ---------------------------- DROP TABLE IF EXISTS `sys_role`; CREATE TABLE `sys_role` ( `id` int(64) NOT NULL, `available` varchar(8) DEFAULT NULL, `description` varchar(32) DEFAULT NULL, `role` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of sys_role -- ---------------------------- INSERT INTO `sys_role` VALUES ('1', '1', '管理員', 'admin'); INSERT INTO `sys_role` VALUES ('2', '1', 'VIP會員', 'vip'); -- ---------------------------- -- Table structure for `sys_role_permission` -- ---------------------------- DROP TABLE IF EXISTS `sys_role_permission`; CREATE TABLE `sys_role_permission` ( `permission_id` int(64) NOT NULL COMMENT '權(quán)限表主鍵', `role_id` int(64) NOT NULL COMMENT '角色表主鍵' ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of sys_role_permission -- ---------------------------- INSERT INTO `sys_role_permission` VALUES ('1', '1'); INSERT INTO `sys_role_permission` VALUES ('2', '1'); -- ---------------------------- -- Table structure for `sys_user_role` -- ---------------------------- DROP TABLE IF EXISTS `sys_user_role`; CREATE TABLE `sys_user_role` ( `role_id` int(64) NOT NULL, `user_id` int(64) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of sys_user_role -- ---------------------------- INSERT INTO `sys_user_role` VALUES ('1', '1'); -- ---------------------------- -- Table structure for `user_info` -- ---------------------------- DROP TABLE IF EXISTS `user_info`; CREATE TABLE `user_info` ( `id` int(64) NOT NULL AUTO_INCREMENT, `name` varchar(32) DEFAULT NULL, `password` varchar(64) DEFAULT NULL, `salt` varchar(64) DEFAULT NULL, `state` varchar(8) DEFAULT NULL, `username` varchar(32) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of user_info -- ---------------------------- INSERT INTO `user_info` VALUES ('1', '管理員', 'd3c59d25033dbf980d29554025c23a75', '8d78869f470951332959580424d4bf4f', '1', 'admin');
最后聲明下?。?!我的開發(fā)環(huán)境是windows10+JDK1.8+springboot2.1.7+shiro1.4.0
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- SpringBoot+Shiro+Redis+Mybatis-plus 實(shí)戰(zhàn)項(xiàng)目及問題小結(jié)
- 解決springboot+shiro 權(quán)限攔截失效的問題
- Springboot和bootstrap實(shí)現(xiàn)shiro權(quán)限控制配置過程
- SpringBoot + Shiro前后端分離權(quán)限
- SpringBoot 整合 Shiro 密碼登錄與郵件驗(yàn)證碼登錄功能(多 Realm 認(rèn)證)
- Springboot shiro認(rèn)證授權(quán)實(shí)現(xiàn)原理及實(shí)例
- SpringBoot整合Shiro實(shí)現(xiàn)登錄認(rèn)證的方法
- Springboot+Shiro+Mybatis+mysql實(shí)現(xiàn)權(quán)限安全認(rèn)證的示例代碼
相關(guān)文章
Spring項(xiàng)目中使用Junit單元測試并配置數(shù)據(jù)源的操作
這篇文章主要介紹了Spring項(xiàng)目中使用Junit單元測試并配置數(shù)據(jù)源的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09Java實(shí)現(xiàn)添加條形碼到PDF表格的方法詳解
條碼的應(yīng)用已深入生活和工作的方方面面。本文以操作PDF文件為例,介紹如何利用Java語言在編輯表格時(shí),向單元格中添加條形碼,感興趣的可以學(xué)習(xí)一下2022-06-06java 中Comparable與Comparator詳解與比較
這篇文章主要介紹了java 中Comparable與Comparator詳解與比較的相關(guān)資料,需要的朋友可以參考下2017-04-04