基于springboot实现整合shiro实现登录认证以及授权过程解析
这篇文章主要介绍了基于springboot实现整合shiro实现登录认证以及授权过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
1.添加shiro的依赖
org.apache.shiro shiro-spring-boot-web- starter 1.4.0
2.先创建一个Realm
publicclassMyShiroRealmextendsAuthorizingRealm{ @Autowired privateRoleServiceroleService;//角色模模块 @Autowired privateUserServiceuserService;//用户模块 @Autowired privatePermissionServicepermissionService;//权限模块 /** *用户身份识别(登录") *@paramauthenticationToken *@return *@throwsAuthenticationException */ @Override protectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationTokenauthenticationToken)throwsAuthenticationException{ UsernamePasswordTokenauthToken=(UsernamePasswordToken)authenticationToken; //获取用户输入的账号 StringuserName=authToken.getUsername(); //通过账号查找用户信息 Useruser=userService.selectUserOne(userName);//将账户名,密码,盐值,getName()实例化到SimpleAuthenticationInfo中交给Shiro来管理 SimpleAuthenticationInfoauthenticationInfo=newSimpleAuthenticationInfo( user, user.getPassWord(), //这里是设置的密码盐 ByteSource.Util.bytes(user.getSalt()), getName()); returnauthenticationInfo; } /** *访问控制。比如某个用户是否具有某个操作的使用权限 *@paramprincipalCollection *@return */ @Override protectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipalCollection){ SimpleAuthorizationInfosimpleAuthorizationInfo=newSimpleAuthorizationInfo(); StringuserName=(String)principalCollection.getPrimaryPrincipal(); if(userName==null){ log.error("授权失败,用户信息为空!!!"); returnnull; } try{ //获取用户角色集 SetlistRole=roleService.findRoleByUsername(userName); simpleAuthorizationInfo.addRoles(listRole); //通过角色获取权限集 for(Stringrole:listRole){ Set permission=permissionService.findPermissionByRole(role); simpleAuthorizationInfo.addStringPermissions(permission); } returnsimpleAuthorizationInfo; }catch(Exceptione){ log.error("授权失败,请检查系统内部错误!!!",e); } returnsimpleAuthorizationInfo; } }
3.创建shiro的配置类
@Configuration publicclassShiroConfiguration{ //配置自定义的Realm @Bean publicMyShiroRealmmyShiroRealm(HashedCredentialsMatchermatcher){ MyShiroRealmmyShiroRealm=newMyShiroRealm(); //在这里配置密码加密 myShiroRealm.setCredentialsMatcher(matcher); returnmyShiroRealm; } //将Realm注册到securityManager中 @Bean publicDefaultWebSecurityManagersecurityManager(HashedCredentialsMatchermatcher){ DefaultWebSecurityManagersecurityManager=newDefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm(matcher)); returnsecurityManager; } //如果没有此name,将会找不到shiroFilter的Bean @Bean(name="shiroFilter") publicShiroFilterFactoryBeanshiroFilter(org.apache.shiro.mgt.SecurityManagersecurityManager){ ShiroFilterFactoryBeanshiroFilterFactoryBean=newShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login");//表示指定登录页面 shiroFilterFactoryBean.setSuccessUrl("/user/list");//登录成功后要跳转的链接 shiroFilterFactoryBean.setUnauthorizedUrl("/403");//未授权页面 MapfilterChainDefinitionMap=newLinkedHashMap<>();//拦截器,配置不会被拦截的链接顺序判断 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都必须认证通过才可以访问;anon:所有url都都可以匿名访问 //filterChainDefinitionMap.put("/**","user");//user表示配置记住我或认证通过可以访问的地址 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); returnshiroFilterFactoryBean; } /** *SpringShiroFilter首先注册到spring容器 *然后被包装成FilterRegistrationBean *最后通过FilterRegistrationBean注册到servlet容器 *@return */ @Bean publicFilterRegistrationBeandelegatingFilterProxy(){ FilterRegistrationBeanfilterRegistrationBean=newFilterRegistrationBean(); DelegatingFilterProxyproxy=newDelegatingFilterProxy(); proxy.setTargetFilterLifecycle(true); proxy.setTargetBeanName("shiroFilter"); filterRegistrationBean.setFilter(proxy); returnfilterRegistrationBean; } //设置cookie @Bean publicSimpleCookierememberMeCookie(){ //这个参数是cookie的名称,对应前端的checkbox的name=rememberMe SimpleCookiesimpleCookie=newSimpleCookie("rememberMe"); //记住我cookie生效时间3个小时(单位秒) simpleCookie.setMaxAge(10800); returnsimpleCookie; } //cookie管理对象,记住我功能 @Bean publicCookieRememberMeManagerrememberMeManager(){ CookieRememberMeManagercookieRememberMeManager=newCookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); returncookieRememberMeManager; } /** *密码匹配凭证管理器(密码加密需要此配置) *@return */ @Bean(name="hashedCredentialsMatcher") publicHashedCredentialsMatcherhashedCredentialsMatcher(){ HashedCredentialsMatcherhashedCredentialsMatcher=newHashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("MD5"); hashedCredentialsMatcher.setHashIterations(1024);//设置加密次数 returnhashedCredentialsMatcher; } //如果没有这两个配置,可能会授权失败,所以依赖中还需要配置aop的依赖 @Bean publicAuthorizationAttributeSourceAdvisorauthorizationAttributeSourceAdvisor(HashedCredentialsMatchermatcher){ AuthorizationAttributeSourceAdvisorauthorizationAttributeSourceAdvisor=newAuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager(matcher)); returnauthorizationAttributeSourceAdvisor; } @Bean @ConditionalOnMissingBean publicDefaultAdvisorAutoProxyCreatordefaultAdvisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreatordefaultAdvisorAutoProxyCreator=newDefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); returndefaultAdvisorAutoProxyCreator; } }
4.新建controller并写个登录的方法
/** *登录页面这里对应shiro中配置的shiroFilter的登录方法 *@return */ @GetMapping("/login") publicStringlogin(){ return"user/login"; }
//登录方法 @PostMapping("/userLogin") publicStringtoLogin(StringuserName,StringpassWord,Modelmodel){ UsernamePasswordTokentoken=newUsernamePasswordToken(userName,passWord); Subjectsubject=SecurityUtils.getSubject(); try{ //这里直接使用shiro的登录方法 subject.login(token); return"redirect:user/list"; //登录失败时,会catch到你的异常,异常通过全局处理 }catch(UnknownAccountExceptione){ model.addAttribute("msg","该账号不存在"); }catch(IncorrectCredentialsExceptione){ model.addAttribute("msg","密码错误,请重试"); }catch(LockedAccountExceptione){ model.addAttribute("msg","该账户已被锁定,请联系管理员"); }catch(Exceptione){ model.addAttribute("msg","登录失败"); } return"user/login"; } //添加 @RequestMapping("/insertUser") @ResponseBody publicintinsertUser(Useruser){ //将uuid设置为密码盐值 Stringsalt=UUID.randomUUID().toString().replaceAll("-",""); SimpleHashsimpleHash=newSimpleHash("MD5",user.getPassWord(),salt,1024); //添加用户信息 user.setPassWord(simpleHash.toHex()).setValid(1).setSalt(salt).setCreateTime(newDate()).setDel(0); returnuserMapper.insertSelective(user); }
5.创建全局异常处理类
@RestControllerAdvice publicclassGlobalExceptionHandle{ @ExceptionHandler(ShiroException.class) publicStringdoHandleShiroException(ShiroExceptionse,Modelmodel){ se.printStackTrace(); if(seinstanceofUnknownAccountException)return"账户不存在!"; elseif(seinstanceofLockedAccountException)return"账户已锁定,请联系管理员"; elseif(seinstanceofIncorrectCredentialsException)return"密码错误,请重试"; elseif(seinstanceofAuthorizationException)return"没有相应权限,请联系管理员"; elsereturn"登录失败"; } }
权限需要开启权限注解才生效
@GetMapping("/userPageList") @ResponseBody @RequiresPermissions("user:view")//这里是用户对应的权限 publicPageListlistPage(HttpServletRequestrequest){ PageListpageList=newPageList(); Listlist=userService.findAllPage(request);//查询出的条数 inttotalCount=userService.countAll();//总记录数 pageList.setRows(list); pageList.setTotal(totalCount); returnpageList; }
shiro用户角色和权限表
--Tablestructurefor`sys_permission` DROPTABLEIFEXISTS`sys_permission`; CREATETABLE`sys_permission`( `id`int(64)NOTNULLAUTO_INCREMENT, `name`varchar(32)DEFAULTNULL, `permission`varchar(32)DEFAULTNULL, `url`varchar(64)DEFAULTNULL, PRIMARYKEY(`id`) )ENGINE=InnoDBAUTO_INCREMENT=4DEFAULTCHARSET=utf8; ------------------------------ --Recordsofsys_permission ------------------------------ INSERTINTO`sys_permission`VALUES('1','用户管理','user:view','user/userPageList'); INSERTINTO`sys_permission`VALUES('2','用户添加','user:add','user/saveUser'); INSERTINTO`sys_permission`VALUES('3','用户删除','user:del','user/delById'); ------------------------------ --Tablestructurefor`sys_role` ------------------------------ DROPTABLEIFEXISTS`sys_role`; CREATETABLE`sys_role`( `id`int(64)NOTNULL, `available`varchar(8)DEFAULTNULL, `description`varchar(32)DEFAULTNULL, `role`varchar(32)DEFAULTNULL, PRIMARYKEY(`id`) )ENGINE=InnoDBDEFAULTCHARSET=utf8; ------------------------------ --Recordsofsys_role ------------------------------ INSERTINTO`sys_role`VALUES('1','1','管理员','admin'); INSERTINTO`sys_role`VALUES('2','1','VIP会员','vip'); ------------------------------ --Tablestructurefor`sys_role_permission` ------------------------------ DROPTABLEIFEXISTS`sys_role_permission`; CREATETABLE`sys_role_permission`( `permission_id`int(64)NOTNULLCOMMENT'权限表主键', `role_id`int(64)NOTNULLCOMMENT'角色表主键' )ENGINE=InnoDBDEFAULTCHARSET=utf8; ------------------------------ --Recordsofsys_role_permission ------------------------------ INSERTINTO`sys_role_permission`VALUES('1','1'); INSERTINTO`sys_role_permission`VALUES('2','1'); ------------------------------ --Tablestructurefor`sys_user_role` ------------------------------ DROPTABLEIFEXISTS`sys_user_role`; CREATETABLE`sys_user_role`( `role_id`int(64)NOTNULL, `user_id`int(64)NOTNULL )ENGINE=InnoDBDEFAULTCHARSET=utf8; ------------------------------ --Recordsofsys_user_role ------------------------------ INSERTINTO`sys_user_role`VALUES('1','1'); ------------------------------ --Tablestructurefor`user_info` ------------------------------ DROPTABLEIFEXISTS`user_info`; CREATETABLE`user_info`( `id`int(64)NOTNULLAUTO_INCREMENT, `name`varchar(32)DEFAULTNULL, `password`varchar(64)DEFAULTNULL, `salt`varchar(64)DEFAULTNULL, `state`varchar(8)DEFAULTNULL, `username`varchar(32)DEFAULTNULL, PRIMARYKEY(`id`) )ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=utf8; ------------------------------ --Recordsofuser_info ------------------------------ INSERTINTO`user_info`VALUES('1','管理员','d3c59d25033dbf980d29554025c23a75','8d78869f470951332959580424d4bf4f','1','admin');
最后声明下!!!我的开发环境是windows10+JDK1.8+springboot2.1.7+shiro1.4.0
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。