基于SpringBoot2的Shiro最简配置操作(两个文件)
基础环境:依赖
org.springframework.boot spring-boot-starter-parent 2.2.1.RELEASE
org.apache.shiro shiro-spring-boot-starter 1.4.0
如果不是前后端分离,要实现页面级的权限控制,则加入以下依赖就可以使用shiro的权限标签了(记得在html头部加上相应约束:
): com.github.theborakompanioni thymeleaf-extras-shiro 2.0.0
Realm:认证鉴权器
packagecom.rz.monomer.modules.shiro; importcom.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; importcom.rz.monomer.modules.user.entity.SysUserInfo; importcom.rz.monomer.modules.user.entity.SysUserRole; importcom.rz.monomer.modules.user.service.SysButtonInfoService; importcom.rz.monomer.modules.user.service.SysUserInfoService; importcom.rz.monomer.modules.user.service.SysUserRoleService; importlombok.extern.slf4j.Slf4j; importorg.apache.shiro.authc.AuthenticationException; importorg.apache.shiro.authc.AuthenticationInfo; importorg.apache.shiro.authc.AuthenticationToken; importorg.apache.shiro.authc.SimpleAuthenticationInfo; importorg.apache.shiro.authz.AuthorizationInfo; importorg.apache.shiro.authz.SimpleAuthorizationInfo; importorg.apache.shiro.realm.AuthorizingRealm; importorg.apache.shiro.subject.PrincipalCollection; importjava.util.Set; importjava.util.stream.Collectors; /** *认证、鉴权类(必须) * *@authorsunziwen *@version1.0 *@date2019/11/1414:06 **/ @Slf4j publicclassShiroRealmextendsAuthorizingRealm{ //以下三个服务是普通Dao查询,从数据库查询用户及其角色权限信息(这个类没有自动注入,需要在下个文件中手动注入) privateSysUserInfoServiceuserInfoService; privateSysButtonInfoServicebuttonInfoService; privateSysUserRoleServiceuserRoleService; publicShiroRealm(SysUserInfoServiceuserInfoService,SysButtonInfoServicebuttonInfoService,SysUserRoleServiceuserRoleService){ this.userInfoService=userInfoService; this.buttonInfoService=buttonInfoService; this.userRoleService=userRoleService; } @Override protectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipals){ log.info("checkauthorizationinfo"); SimpleAuthorizationInfoauthInfo=newSimpleAuthorizationInfo(); //获取当前用户 SysUserInfouserInfo=(SysUserInfo)principals.getPrimaryPrincipal(); //查询角色信息 SetuserRoles=userRoleService.list(newLambdaQueryWrapper ().eq(SysUserRole::getUserId,userInfo.getId())) .stream() .map(SysUserRole::getRoleId) .collect(Collectors.toSet()); //角色所有权限 Set perms=buttonInfoService.getPermsByRoles(userRoles); authInfo.addStringPermissions(perms); returnauthInfo; } @Override protectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokentoken)throwsAuthenticationException{ log.info("checkauthenticationinfo"); Stringusername=(String)token.getPrincipal(); //获取用户信息 SysUserInfouser=userInfoService.getOne(newLambdaQueryWrapper ().eq(SysUserInfo::getUsername,username)); if(user==null){ returnnull; } /*SimpleAuthenticationInfoauthenticationInfo=newSimpleAuthenticationInfo(user,user.getPassword(), ByteSource.Util.bytes(654321),getName());*/ SimpleAuthenticationInfoauthenticationInfo=newSimpleAuthenticationInfo(user,user.getPassword(),getName()); returnauthenticationInfo; } }
WebSecurityManager:安全管理器
packagecom.rz.monomer.modules.shiro; importcom.rz.monomer.modules.user.service.SysButtonInfoService; importcom.rz.monomer.modules.user.service.SysUserInfoService; importcom.rz.monomer.modules.user.service.SysUserRoleService; importlombok.AllArgsConstructor; importlombok.extern.slf4j.Slf4j; importorg.apache.shiro.spring.web.ShiroFilterFactoryBean; importorg.apache.shiro.web.filter.authc.FormAuthenticationFilter; importorg.apache.shiro.web.filter.authc.LogoutFilter; importorg.apache.shiro.web.mgt.DefaultWebSecurityManager; importorg.springframework.context.annotation.Bean; importorg.springframework.context.annotation.Configuration; importjavax.servlet.Filter; importjava.util.LinkedHashMap; importjava.util.Map; /** *Shiro配置类(必须) * *@authorsunziwen *@version1.0 *@date2019/11/1414:08 **/ @Configuration @Slf4j @AllArgsConstructor publicclassWebSecurityManager{ privateSysUserInfoServiceuserInfoService; privateSysButtonInfoServicebuttonInfoService; privateSysUserRoleServiceuserRoleService; /** *安全管理器 */ @Bean publicDefaultWebSecurityManagersecurityManager(){ DefaultWebSecurityManagersecurityManager=newDefaultWebSecurityManager(); securityManager.setRealm(realm()); returnsecurityManager; } /** *认证鉴权器(安全管理器的依赖) */ @Bean publicShiroRealmrealm(){ returnnewShiroRealm(userInfoService,buttonInfoService,userRoleService); } /** *配置拦截规则 */ @Bean publicShiroFilterFactoryBeanfilter(org.apache.shiro.mgt.SecurityManagersecurityManager){ log.info("configshirofilter"); ShiroFilterFactoryBeanshiroFilterFactoryBean=newShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //定义URL拦截链 MapfilterChainDefinitionMap=newLinkedHashMap (); //允许匿名用户访问首页 filterChainDefinitionMap.put("/shiro/index","anon"); //定义注销路径 filterChainDefinitionMap.put("/shiro/logout","logout"); //所有用户界面都需要身份验证,否则会跳转到loginurl,由FormAuthenticationFilter处理 filterChainDefinitionMap.put("/shiro/user/**","authc"); //为login路径定义拦截,由FormAuthenticationFilter处理 filterChainDefinitionMap.put("/shiro/login","authc"); //所有vip路径要求具备vip角色权限 filterChainDefinitionMap.put("/shiro/vip/**","roles[vip]"); //指定loginurl路径 shiroFilterFactoryBean.setLoginUrl("/shiro/login"); //登录成功后跳转路径 shiroFilterFactoryBean.setSuccessUrl("/shiro/user/"); //forunauthenticated shiroFilterFactoryBean.setUnauthorizedUrl("/shiro/unauth"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); //自定义filters,可覆盖默认的Filter列表,参考DefaultFilter Map filters=newLinkedHashMap (); //定制logout过滤,指定注销后跳转到登录页(默认为根路径) LogoutFilterlogoutFilter=newLogoutFilter(); logoutFilter.setRedirectUrl("/shiro/login"); filters.put("logout",logoutFilter); //定制authc过滤,指定登录表单参数 FormAuthenticationFilterauthFilter=newFormAuthenticationFilter(); authFilter.setUsernameParam("username"); authFilter.setPasswordParam("password"); filters.put("authc",authFilter); shiroFilterFactoryBean.setFilters(filters); returnshiroFilterFactoryBean; } }
Test:登录测试
packagecom.rz.monomer.modules.user.controller; importcom.rz.monomer.commons.utils.Md5Encrypt; importlombok.extern.slf4j.Slf4j; importorg.apache.shiro.SecurityUtils; importorg.apache.shiro.authc.*; importorg.apache.shiro.authz.annotation.RequiresAuthentication; importorg.apache.shiro.subject.Subject; importorg.springframework.stereotype.Controller; importorg.springframework.web.bind.annotation.*; @RestController @Slf4j publicclassLoginController{ @PostMapping("/login") publicStringlogin(@RequestParam("username")Stringusername,@RequestParam("password")Stringpassword){ Subjectsubject=SecurityUtils.getSubject(); AuthenticationTokentoken=newUsernamePasswordToken(username,Md5Encrypt.md5(password)); try{ //执行登录 subject.login(token); }catch(UnknownAccountExceptione){ //未知用户 log.warn("theaccount{}isnotfound",username); return"accountnotfound"; }catch(IncorrectCredentialsExceptione){ //用户或密码不正确 log.warn("theaccountorpasswordisnotcorrect"); return"accountorpasswordnotcorrect"; } return"loginsuccess"; } }
补充:SpringBoot配置Shiro时踩坑
在SpringBoot2.0整合shiro时使用@EnableAutoConfiguration的时候需要对config文件进行扫描,即使用@ComponentScan对配置进行扫描。
或者直接使用@SpringBootApplication,但是这种方法会将主方法目录下的所有package都进行扫描影响项目效率。
Authenticationfailedfortokensubmission[org.apache.shiro.authc.UsernamePasswordToken-zxc,rememberMe=false].Possibleunexpectederror?(TypicalorexpectedloginexceptionsshouldextendfromAuthenticationException
当出现此异常时,一般情况是用户名密码不匹配,或者是在配置对应的Realm时出现空值导致匹配失败。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持毛票票。如有错误或未考虑完全的地方,望不吝赐教。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。