要将shiro与web集成必须要添加shiro-spring依赖:
org.apache.shiro
shiro-spring
1.4.0
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* 结合spring,shiro完成web的认证和授权
*/
@Configuration
public class ShiroConfig {
@Bean
public DefaultSecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(definedRealm());
return securityManager;
}
@Bean
public DefinedRealm definedRealm(){
DefinedRealm realm = new DefinedRealm();
return realm;
}
@Bean
public ShiroFilterFactoryBean shiroFilter(){
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager());
shiroFilter.setLoginUrl("/login");//设置登录URL
shiroFilter.setUnauthorizedUrl("/403");//设置未授权URL
shiroFilter.setSuccessUrl("/index");//设置登录成功后跳转URL
//设置拦截的路径
Map filterChain = new LinkedHashMap<>();
filterChain.put("/logout","logout");
filterChain.put("/css/**","anon");
filterChain.put("/fonts/**","anon");
filterChain.put("/images/**","anon");
filterChain.put("/js/**","anon");
filterChain.put("/login","anon");
filterChain.put("/list","roles[frame]");
filterChain.put("/**","authc");//设置在最后,按照顺序判断,如果匹配则返回
shiroFilter.setFilterChainDefinitionMap(filterChain);
return shiroFilter;
}
}
登录控制器:
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class LoginController {
@RequestMapping(value = "/login",method = RequestMethod.GET)
public String login(){
System.out.println("首页登录");
return "login";
}
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(String username,String password){
System.out.println("开始验证登录信息,username " + username );
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123");
try {
subject.login(token);
return "index";
}catch (Exception e){
e.printStackTrace();
}
return "login";
}
@RequestMapping("/index")
public String index(){
System.out.println("登录成功");
return "index";
}
@RequestMapping("/403")
public String error(){
System.out.println("请先登录");
return "403";
}
}
以上简单实现了shiro和web的集成。集合以上shiro配置代码和POST请求方式的login()方法,与上一节的登录控制器比较,发现其实我们只是将realm和securityManager的Bean交个spring容器来管理。
上一节登录控制器如下:
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//设置realm
securityManager.setRealm(definedRealm);
//绑定securityManager到securityUtils
SecurityUtils.setSecurityManager(securityManager);
//创建登录实体
Subject subject = SecurityUtils.getSubject();
//创建登录token
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","01d7f40760960e7bd9443513f22ab9af");
//登录
subject.login(token);
并且再配置ShiroFilterFactoryBean。通过该类来配置我们loginUrl、UnauthorizedUrl、SuccessUrl,以及用户访问时需要认证和鉴权的URL。
配置URL通配符的规则:
后面的选项只能在下面的 表格中选择:
其次是授权相关的,当我们配置如下过滤器,鉴权没通过是,将会跳转到配置的UnauthorizedUrl。一般很少使用,因为使用注解会更方便
上面提到了注解做鉴权,下面来看看如何使用shiro的注解鉴权。
首先是启用shiro-spring的aop,在shiro配置类中增加如下配置:
/**
* Spring的一个bean,有advisor决定对那些类实现AOP代理
* 配置通过注解完成权限和角色验证
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator defaultAdvisor = new DefaultAdvisorAutoProxyCreator();
defaultAdvisor.setProxyTargetClass(true);
return defaultAdvisor;
}
/**
* shiro类的实现Advisor的类,开启shiro的注解支持
* 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor
* 拦截@RequiredRoles,@RequiredPermission注解的方法
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager());
return advisor;
}
/**
* shiro生命周期处理器
* @return
*/
@Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
在loginController中增加如下接口:
@RequiresRoles("admin")
@RequestMapping("list")
public String list(){
return "list";
}
当我们登录成功后,再去访问该接口时,如果当前登录用户没有该角色将会抛出org.apache.shiro.authz.AuthorizationException异常。
以上就是shiro和web的初步结合,下一节来探讨shiro中会话管理