Shiro简单入门-Springboot
学习视频:【狂神说Java】SpringBoot整合Shiro框架
真正的大师永远保持着一颗学徒的心
目录
Shiro简介
Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications
ApacheShiro™是一个功能强大且易于使用的JAVA安全框架,用于执行身份验证、授权、加密和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地保护任何应用程序–从最小的移动应用程序到最大的Web和企业应用程序
学习
说明:
狂神的视频是没有前后端分离,用的是Thymeleaf,我用的是前后端分离,理论上传递的都是json字符串,所有
看视频可能有点懵
快速开始
public class Quickstart {
private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
public static void main(String[] args) {
//初始化Ini的Realm
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
//设置安全工具的管理器
SecurityUtils.setSecurityManager(securityManager);
//获取Subject
Subject currentUser = SecurityUtils.getSubject();
//获取Session
Session session = currentUser.getSession();
//设置相关参数
session.setAttribute("someKey", "aValue");
String value = (String) session.getAttribute("someKey");
if (value.equals("aValue")) {
log.info("Retrieved the correct value! [" + value + "]");
}
//判断当前用户是否认证
if (!currentUser.isAuthenticated()) {
//新建认证令牌
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
//设置记住我
token.setRememberMe(true);
try {
//登录
currentUser.login(token);
} catch (UnknownAccountException uae) {
//用户名不存在
log.info("There is no user with username of " + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
//密码错误
log.info("Password for account " + token.getPrincipal() + " was incorrect!");
} catch (LockedAccountException lae) {
//用户被锁定
log.info("The account for username " + token.getPrincipal() + " is locked. " +
"Please contact your administrator to unlock it.");
}
//总异常:认证异常
catch (AuthenticationException ae) {
}
}
//currentUser.getPrincipal() -> 获取用户一些信息
log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");
//判断是否拥有角色
if (currentUser.hasRole("schwartz")) {
log.info("May the Schwartz be with you!");
} else {
log.info("Hello, mere mortal.");
}
//判断是否拥有权限 -> 简单权限
if (currentUser.isPermitted("lightsaber:wield")) {
log.info("You may use a lightsaber ring. Use it wisely.");
} else {
log.info("Sorry, lightsaber rings are for schwartz masters only.");
}
//判断是否拥有权限 -> 高级的权限
if (currentUser.isPermitted("winnebago:drive:eagle5")) {
log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " +
"Here are the keys - have fun!");
} else {
log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}
//退出
currentUser.logout();
System.exit(0);
}
}
整合Springboot(基础)
导入jar包
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring-boot-web-starter -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
编写自定义Realm
public class RolesRealm extends AuthorizingRealm {
@Override
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
@Override
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
return null;
}
}
编写配置文件
@Configuration
public class ShiroConfig {
public RolesRealm realm() {
RolesRealm realm = new RolesRealm();
return realm;
}
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm());
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
//map
Map<String, String> map = new LinkedHashMap<>();
map.put("/", "anon");
map.put("/user/add", "authc");
//添加shiro内置的过滤器
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
}
自定义未登录返回状态:(正常情况会重定向到一个页面,如果是前后端分离,我们希望返回json字符串)
shiro自定义未登录返回状态
认证
RolesRealm
public class RolesRealm extends AuthorizingRealm {
@Override
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
@Override
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = "admin";
String password = "admin";
//只需要验证用户名
UsernamePasswordToken selfToken = (UsernamePasswordToken)token;
if (!username.equals(selfToken.getUsername())) {
return null;
}
//只需要返回的时候返回正确的密码,shiro内部就可以自动验证密码
return new SimpleAuthenticationInfo(username, password, "");
}
}
登录逻辑
@GetMapping("login")
public String login(
@RequestParam(value = "username", required = true)String username,
@RequestParam(value = "password", required = true)String password) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
try {
subject.login(usernamePasswordToken);
return "success";
} catch (AuthenticationException e) {
// TODO: handle exception
return "username or password error";
}
}
授权
配置增加授权
map.put("/user/delete", "perms[user:delete]");放在上面
修改realm
@Override
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
System.err.println("进行认证");
info.addStringPermission("user:delete");
return info;
}
最后
注意:在设置拦截器的时候
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean() {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager());
//map
Map<String, String> map = new LinkedHashMap<>();
map.put("/", "anon");
map.put("/user/delete", "perms[user:delete]");
map.put("/user/*", "authc");
//添加shiro内置的过滤器
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
//用户未登录不进行跳转,而是自定义返回json数据
Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();//获取filters
filters.put("authc", new ShiroLoginFilter());//将自定义 的FormAuthenticationFilter注入shiroFilter中
filters.put("perms", new ShiroPermsFilter());
return shiroFilterFactoryBean;
}
拦截器的顺序有意义的如果map.put("/user/*", "authc");
放在map.put("/user/delete","perms[user:delete]");
上面,则不会执行授权验证,只会执行登录验证,原因未知
总结
这个博客只是Shiro入门,只是会略微使用Shiro,如果想继续学习,推荐尚硅谷教程:尚硅谷Shiro安全权限框架实战教程全套完整版(从入门到精通)
下篇文章:Shiro正式学习