SpringBoot如何整合Apache Shiro呢?
下文笔者讲述SpringBoot整合Apache Shiro的方法及示例分享,如下所示
Shiro是我们权限认证中经常要使用的框架 那么SpringBoot中如何使用Apache Shiro呢? 下文笔者将一一道来,如下所示 =============================== 1.引入相应的jar包 2.编写 Realm Shiro连接数据的桥梁 Subject 用户主体 (把操作交给SecurityManager) SecurityManager 安全管理器 (关联Realm) 3.编写ShiroConfig 此时以上方法,即可实现SpringBoot使用Shiro的操作例:SpringBoot整合Apache Shiro的示例
引入maven依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
配置自定义Realm
UserRealm.java
package com.shiro;
import com.entity.User;
import com.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Arraylist;
import java.util.List;
/**
* 自定义realm
*/
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 执行授权逻辑
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//给请求进行授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取登录用户信息
Subject subject = SecurityUtils.getSubject();
//取出来的user与下方认证方法中new SimpleAuthenticationInfo(user, user.getPassword(), getName());的第一个存入的参数对应
User user = (User) subject.getPrincipal();
//这里为了做演示,实际开发中需要从数据库获取该用户的权限
List permList = new ArrayList();
permList.add("user:delete");
//添加请求的授权集合
info.addStringPermissions(permList);
return info;
}
/**
* 执行认证逻辑
*
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//查询用户名是否存在
User user = userService.findByUserName(token.getUsername());
if (user == null) {
//用户不存在,shiro底层会抛出UnknownAccountException异常
throw new UnknownAccountException();
}
if (!user.getEnable()) {
throw new LockedAccountException();
}
//通过这个进行认证,并返回 实际使用中密码要进行加密 这里放入的第一个参数user和上面授权方法中subject.getPrincipal();这个取到的内容对应
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), getName());
// 当验证都通过后,把用户信息放在session里
Session session = SecurityUtils.getSubject().getSession();
session.setAttribute("user", user);
return simpleAuthenticationInfo;
}
}
shiro配置类
ShiroConfig.java
package com.shiro;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* shiro配置类
*/
@Configuration
public class ShiroConfig {
/**
* 创建shiroFilterFatoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(){
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());
//添加shiro内置过滤器
/**
* shiro内置过滤器,可以实现权限相关的拦截器功能
* 常用的过滤器
* anon:无需认证(登录)可以访问
* authc:必须认证才可以访问
* user:如果使用rememberMe的功能可以直接访问
* perms:该资源必须得到资源权限才可以访问
* role:该资源必须得到角色权限才可以访问
*
*/
Map<String,String> filterMap=new LinkedHashMap<>();
filterMap.put("/back/*","authc");
//放行登录页面和登录提交请求
filterMap.put("/login","anon");
filterMap.put("/toLogin","anon");
/**
* 授权过滤器,表示用户执行 “/delete” 操作需要有 “user:delete” 的授权
* 当前授权拦截后,shiro会自动跳转到未授权页面
*/
filterMap.put("/delete","perms[user:delete]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
//设置登录页面的请求链接
shiroFilterFactoryBean.setLoginUrl("/toLogin");
//设置未授权时的跳转链接
shiroFilterFactoryBean.setUnauthorizedUrl("/toUnauthorizedUrl");
return shiroFilterFactoryBean;
}
/**
* 创建DefaultWebSecurityManager
*/
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
//关联realm
securityManager.setRealm(getRealm());
return securityManager;
}
/**
* 创建Realm
*/
@Bean
public UserRealm getRealm(){
return new UserRealm();
}
}
配置规则详细说明
// 将需要配置的地址放入map中,规则如下:
/**
anon:例子/admins/**=anon 没有参数,表示可以匿名使用。
authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数
roles(角色):例子/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,
并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles["admin,guest"],
每个参数通过才算通过,相当于hasAllRoles()方法。
perms(权限):例子/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,
并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],
当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
rest:例子/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,
其中method为post,get,delete等。
port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到
schemal://serverName:8081?queryString,其中schmal是协议http或https等,
serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。
authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证
ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https
user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查
*/
// 详情参考shiro.web.filter源码
控制器类,登录 退出方法
LoginController.java
package com.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class LoginController {
/**
* 登录请求方法
*
* @param username 用户名
* @param password 密码
* @return
*/
@PostMapping(value = "/login")
public String loginPost(String username, String password) {
/**
* 使用Shiro进行认证操作
*/
//获取Subject
Subject subject = SecurityUtils.getSubject();
//封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//是否记住我操作,这里我默认设置记住我
token.setRememberMe(true);
//执行登录方法
try {
subject.login(token);
//登录成功操作
} catch (UnknownAccountException e) {
//用户不存在
e.printStackTrace();
} catch (IncorrectCredentialsException e) {
//用户名密码错误
e.printStackTrace();
} catch (LockedAccountException e) {
e.printStackTrace();
//账号被禁用
}
return null;
}
/**
* 登出
*
* @return
*/
@RequestMapping("/logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
Session session = subject.getSession();
//情况session中的用户信息
session.removeAttribute("user");
//返回登录页
return "login";
}
}
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


