shiro整合springboot
Shiro
1.什么是
- 安全权限框架
- 功能:授权,认证
2.quickstart
public class Tutorial {
private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class);
public static void main(String[] args) {
log.info("My First Apache Shiro Application");
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
// get the currently executing user:
//获取当前的用户对象:subject,调用SecurityUtils.getSubject();
Subject currentUser = SecurityUtils.getSubject();
// Do some stuff with a Session (no need for a web or EJB container!!!)
//测试使用session
//获取session currentUser.getSession();
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 + "]");//
}
// let's login the current user so we can check against roles and permissions:
//测试当前的用户是否已经被认证,即是否已经登录
//调用Subject的isAuthenticated()
if (!currentUser.isAuthenticated()) {
//把用户名和密码封装为token:令牌
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
//rememberme
token.setRememberMe(true);
try {
//执行登录操作
currentUser.login(token);
}
//若没有指定的账户,则shiro抛出异常UnknownAccountException
catch (UnknownAccountException uae) {
log.info("There is no user with username of " + token.getPrincipal());
}
//若账户存在,密码不匹配,则shiro抛出 IncorrectCredentialsException异常
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 more exceptions here (maybe custom ones specific to your application?
//所有异常的父类
catch (AuthenticationException ae) {
//unexpected condition? error?
}
}
//say who they are:
//print their identifying principal (in this case, a username):
log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");
//test a role:
if (currentUser.hasRole("schwartz")) {
log.info("May the Schwartz be with you!");
} else {
log.info("Hello, mere mortal.");
}
//test a typed permission (not instance-level) 粗粒度
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.");
}
//a (very powerful) Instance Level permission: 细粒度
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!");
}
//注销
//all done - log out!
currentUser.logout();
//结束系统
System.exit(0);
}
}
quickstart这三行是固定的
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
集成springboot
shior核心对象
- Subject:用户
- SecurityManager:管理所有用户
- Realm:连接数据
导入shiro整合springboot整合依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.8.0</version>
</dependency>
这两个依赖在后面会用到
<!--thymeleaf-->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
-
编写配置类 ShiroConfig。配置类添加@Configuration注解!!!切记
- ShiroFilterFactoryBean
- DefaultWebSecurityManager
- 创建realm对象,需要自定义类
- 以上三点对应shiro三大对象,从下向上配置
-
自定义的userRealm
-
extends AuthorizingRealm
-
重写两个方法 1.授权 2.认证
public class UserRealm extends AuthorizingRealm { //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=>授权"); return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行了=>认证"); return null; } }
-
-
将UserRealm对象配置进spirng
//创建UserRealm,对象 @Bean(name = "userRealm") public UserRealm userRealm(){ return new UserRealm(); } -
配置DafaultWebSecurityManager
//DefaultWebSecurityManager @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //关联UserRealm securityManager.setRealm(userRealm); return securityManager; } -
创建ShiroFilterFactoryBean
//ShiroFilterFactoryBean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); return bean; }
如何实现对用户的授权操作
-
在ShiroFilterFactoryBean中添加shiro的内置过滤器
-
anno:无需认证就可以访问
-
authc:必须认证了才能访问
-
user: 必须拥有 记住我功能才能访问
-
perms:拥有对某个资源的权限才能访问
-
role:拥有某个角色才能访问
//ShiroFilterFactoryBean @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); //如何实现对用户的授权操作 //在ShiroFilterFactoryBean中添加shiro的内置过滤器 Map<String,String> filterMap = new LinkedHashMap<>(); // /user/add /update 为定义接口 filterMap.put("/user/add","authc"); filterMap.put("/user/update","authc"); bean.setFilterChainDefinitionMap(filterMap); System.err.println("[debug] shiro"); return bean; }通过以上代码可以通过shiro拦截所有的请求
-
设置登录拦截,在上面的代码中添加。(/toLogin为登陆界面)
bean.setLogUrl(/toLogin);
-
用户认证操作,放在UserRealm中
登录controller中
-
获取当前的用户
Subject subject = SecurityUtils.getSubject(); -
封装用户的登录数据 (封装username和password)-- > Token令牌
//封装用户登录数据 UsernamePasswordToken token = new UsernamePasswordToken(username, password); -
subject.login(token);//执行登录方法,没有异常说明ok
-
捕获上一步的异常
try { //执行登录方法 subject.login(token); return "index"; } catch (UnknownAccountException uae) {//用户名不存在 model.addAttribute("msg","用户名不存在"); return "login"; } catch (IncorrectCredentialsException ice) {//密码错误 model.addAttribute("msg","密码错误"); return "login"; } -
UserRealm
//认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("执行了=>认证"); //用户名,密码 ,正常应从数据库中取。这里为了方便,在这里伪造数据 String username = "root"; String password = "123456"; UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; if(!token.getUsername().equals(username)){ return null;//return null 抛出异常,UnknownAccountExecption } return new SimpleAuthenticationInfo("",passsword,""); }

浙公网安备 33010602011771号