springboot整合shiro该怎么办?springboot整合shiro详解

TheDisguiser 2020-04-06 18:32:34 java常见问答 6406

Shiro是现在最为流行饿权限认证开发框架,在项目开发中有时候需要通过springboot整合shiro来实现权限控制,那么,小伙伴们知道springboot如何整合shiro吗?下面就跟小编一起来看看吧。

这里我们使用idea做一个登入认证的例子

一、导入shiro依赖

<dependency>
    <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring-boot-web-        
         starter</artifactId>
    <version>1.4.0</version>
</dependency>

二、创建Realm

public class MyShiroRealm extends AuthorizingRealm {
@Autowired
private RoleService roleService;//角色模模块
@Autowired
private UserService userService;//用户模块
@Autowired
private PermissionService permissionService;//权限模块
/**
* 用户身份识别(登录")
* @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()实例化到SimpleAuthenticationInfo中交给Shiro来管理
SimpleAuthenticationInfo authenticationInfo = new 
SimpleAuthenticationInfo(
user,
user.getPassWord(),
//这里是设置的密码盐
ByteSource.Util.bytes(user.getSalt()),
getName());
return authenticationInfo;
}
/**
* 访问控制。比如某个用户是否具有某个操作的使用权限
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection 
principalCollection) {
SimpleAuthorizationInfo simpleAuthorizationInfo = new 
SimpleAuthorizationInfo();
String userName = (String) principalCollection.getPrimaryPrincipal();
if (userName == null) {
log.error("授权失败,用户信息为空!!!");
return null;
}
try {
//获取用户角色集
Set listRole= roleService.findRoleByUsername(userName);
simpleAuthorizationInfo.addRoles(listRole);
//通过角色获取权限集
for (String role : listRole) {
Set permission= permissionService.findPermissionByRole(role);
simpleAuthorizationInfo.addStringPermissions(permission);
}
return simpleAuthorizationInfo;
} catch (Exception e) {
log.error("授权失败,请检查系统内部错误!!!", e);
}
return simpleAuthorizationInfo;
}
}

三、创建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"); // 登录成功后要跳转的链接
shiroFilterFactoryBean.setUnauthorizedUrl("/403"); //未授权页面
MapfilterChainDefinitionMap = 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都必须认证通过才可以访问; 
anon:所有url都都可以匿名访问
//filterChainDefinitionMap.put("/**", "user"); //user表示配置记住我或认证通过可以访问的地址
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;
}
//设置cookie
@Bean
public SimpleCookie rememberMeCookie(){
//这个参数是cookie的名称,对应前端的checkbox的name=rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//记住我cookie生效时间3个小时(单位秒)
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);// 设置加密次数
return hashedCredentialsMatcher;
}
//如果没有这两个配置,可能会授权失败,所以依赖中还需要配置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;
}
}

四、创建controller并写入登录方法

/**
* 登录页面 这里对应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";
//登录失败时,会catch到你的异常,异常通过全局处理
//model的msg需要在页面获取才能显示具体失败信息
} catch (UnknownAccountException e) {
model.addAttribute("msg","该账号不存在");
} catch (IncorrectCredentialsException e) {
model.addAttribute("msg","密码错误,请重试");
} catch (LockedAccountException e) {
model.addAttribute("msg","该账户已被锁定,请联系管理员");
} catch (Exception e) {
model.addAttribute("msg","登录失败");
}
return "user/login";
}
//添加
@RequestMapping("/insertUser")
@ResponseBody
public int insertUser(User user){
//将uuid设置为密码盐值
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);
}

五、创建全局异常处理类

@RestControllerAdvice
public class GlobalExceptionHandle {
@ExceptionHandler(ShiroException.class)
public String doHandleShiroException(ShiroException se,Model model) {
se.printStackTrace();
//这里从登录方法抓取到异常之后会统一跳转到登录页面
if(se instanceof UnknownAccountException){ //该账号不存在
return "redirect:user/login";
}
if(se instanceof LockedAccountException){ //该账户已被锁定,请联系管理员
return "redirect:user/login";
}
if(se instanceof IncorrectCredentialsException){//密码错误
return "redirect:user/login";
}
if(se instanceof AuthorizationException){ //没有相应权限,请联系管理员
return "redirect:user/login";
}else{ //登录失败
return "redirect:user/login";
}
}
}
权限需要开启权限注解才生效
@GetMapping("/userPageList")
@ResponseBody
@RequiresPermissions("user:view") //这里是用户对应的权限
public PageList listPage(HttpServletRequest request){
PageList pageList = new PageList();
List list= userService.findAllPage(request);//查询出的条数
int totalCount = userService.countAll();//总记录数
pageList.setRows(list);
pageList.setTotal(totalCount);
return pageList;
}

以上就是如何使用springboot整合shiro的所有内容了,你知道了吗?更多相关内容请继续关注本网站吧。