SpringBoot 整合Shiro 实现身份权限验证
具体代码访问链接下载
从项目到部署服务器的过程,毕竟些写项目是为了发布部署服务器。
本篇主要介绍**SpringBoot 整合Shiro 实现身份权限验证**
原理:
1.没有登录情况:访问api接口--->shiro配置拦截——->跳转到shiro配置的setLoginUrl(“”)接口
2.去登陆【前提设置开放登陆接口filterChainDefinitionMap.put("/login", "anon");,不然会被拦截,走步骤1】:
访问登录接口---》进入登录接口处理参数,内部调用subject.login(token)
-----》进入shrio的身份验证方法doGetAuthenticationInfo
-------》通过之后返回登录接口继续之后方法,返回前端
3.登录情况访问api接口:
访问api接口--->shiro配置拦截——->
跳转到shiro的权限验证方法doGetAuthorizationInfo--------》
【不通过跳转到shiro配置的 shiroFilterFactoryBean.setUnauthorizedUrl("/noPermission");】
通过之后进入真正的api接口,返回前端
步骤:
1. springboot的pom文件添加依赖,导入sql.位置在资源目录下
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
1.1配置ShiroConfig
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
shiroFilterFactoryBean.setLoginUrl("/notLogin");
// 设置无权限时跳转的 url;
shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");
// 设置拦截器
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
//游客,开发权限
filterChainDefinitionMap.put("/guest/**", "anon");
//用户,需要角色权限 “user”
filterChainDefinitionMap.put("/user/**", "roles[user]");
//管理员,需要角色权限 “admin”
filterChainDefinitionMap.put("/admin/**", "roles[admin]");
//开放登陆接口
filterChainDefinitionMap.put("/login", "anon");
//其余接口一律拦截
//主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
System.out.println("Shiro拦截器工厂类注入成功");
return shiroFilterFactoryBean;
}
/**
* 注入 securityManager
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(customRealm());
return securityManager;
}
/**
* 自定义身份认证 realm;
* <p>
* 必须写这个类,并加上 @Bean 注解,目的是注入 CustomRealm,
* 否则会影响 CustomRealm类 中其他类的依赖注入
*/
@Bean
public MyShiroRealm customRealm() {
return new MyShiroRealm();
}
2.配置MyShiroRealm
public class MyShiroRealm extends AuthorizingRealm {
private UserInfoService userInfoService;
@Autowired
private void setUserMapper(UserInfoService userInfoService) {
this.userInfoService = userInfoService;
}
/**
* 获取身份验证信息
* Shiro中,最终是通过 Realm 来获取应用程序中的用户、角色及权限信息的。
*
* @param authenticationToken 用户身份信息 token
* @return 返回封装了用户信息的 AuthenticationInfo 实例
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("————身份认证方法————");
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
// 从数据库获取对应用户名密码的用户
String password = userInfoService.getPassword(token.getUsername());
if (null == password) {
throw new AccountException("用户名不正确");
} else if (!password.equals(new String((char[]) token.getCredentials()))) {
throw new AccountException("密码不正确");
}
return new SimpleAuthenticationInfo(token.getPrincipal(), password, getName());
}
/**
* 获取授权信息
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("————权限认证————");
String username = (String) SecurityUtils.getSubject().getPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获得该用户角色
String role = userInfoService.getRole(username);
Set<String> set = new HashSet<>();
//需要将 role 封装到 Set 作为 info.setRoles() 的参数
set.add(role);
//设置该用户拥有的角色
info.setRoles(set);
return info;
}
}
3.登录方法
@RestController
public class LoginController {
@Autowired
private UserInfoService userInfoService;
private Logger logger = LoggerFactory.getLogger(LoginController.class);
@RequestMapping(value = "/notLogin", method = RequestMethod.GET)
public ResultMap notLogin() {
return ResultMap.success().message("您尚未登陆!");
}
@RequestMapping(value = "/notRole", method = RequestMethod.GET)
public ResultMap notRole() {
return ResultMap.success().message("您没有权限!");
}
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public ResultMap logout() {
Subject subject = SecurityUtils.getSubject();
//注销
subject.logout();
return ResultMap.success().message("成功注销!");
}
/**
* 登陆
*
* @param username 用户名
* @param password 密码
*/
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ResultMap login(String username, String password) {
logger.info("登陆-----------------------start");
try {
// 从SecurityUtils里边创建一个 subject
Subject subject = SecurityUtils.getSubject();
// 在认证提交前准备 token(令牌)
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
// 执行认证登陆
subject.login(token);
//根据权限,指定返回数据
String role = userInfoService.getRole(username);
if ("user".equals(role)) {
return ResultMap.success().message("欢迎登陆");
}
if ("admin".equals(role)) {
return ResultMap.success().message("欢迎来到管理员页面");
}
}catch (Exception e) {
logger.error("登录失败,系统异常,异常信息为:{}", e);
e.printStackTrace();
return ResultMap.fail().message("登录失败,系统异常,异常信息为:{}"+e);
}
logger.info("登陆-----------------------end");
return ResultMap.fail().message("权限错误!");
}
}
参考文档《https://www.cnblogs.com/HowieYuan/p/9259638.html》