欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Shiro简单入门-Springboot

程序员文章站 2022-05-03 12:53:03
...

学习视频:【狂神说Java】SpringBoot整合Shiro框架
真正的大师永远保持着一颗学徒的心

目录

Shiro简介

官网:https://shiro.apache.org/

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和企业应用程序

Shiro简单入门-Springboot

学习

说明:
狂神的视频是没有前后端分离,用的是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正式学习