基于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());
//角色所有权限
Setperms=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
Mapfilters=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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。