在springboot中使用shiro的步骤:
1、创建一个springboot中
2、导入下列依赖
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--shiro的依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
3、编写yml文件
4、编写Realm类,用于进行shiro的认证与授权
5、编写配置类,配置shiro的相关信息(以前应该写在applicationContext.xml,现在都在配置类中进行配置)
@@@@@@@@@@类中,至少要包含下列三个方法
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);//设置安全管理器
shiroFilterFactoryBean.setLoginUrl("/login");//如果过滤器拦到用户没有经过认证,发出login请求,找过认证的控制器
//创建一个map,用于指定,哪一些请求路径,shiro如何拦截
Map<String,Object> shiroFilterDefinitionMap = new LinkedHashMap<>();
shiroFilterDefinitionMap.put("/css/**","anon"); //允许匿名访问
shiroFilterDefinitionMap.put("/js/**","anon");
shiroFilterDefinitionMap.put("/img/**","anon");
shiroFilterDefinitionMap.put("/**","authc");//必须认证以后,才允许访问资源
shiroFilterFactoryBean.setFilterChainDefinitionMap(shiroFilterDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//在安全管理器中,注入realm
securityManager.setRealm(authRealm());
return securityManager;
}
@Bean
public AuthRealm authRealm(){
AuthRealm authRealm = new AuthRealm();
return authRealm;
}
6、编写控制器类 FirstController,一开始加载就自动发请求,进行该控制器
@Controller
public class FirstController {
@RequestMapping("/")
public String first(){
System.out.println("-----进入控制器first---------");
return "/main";
}
}
7、编写main.html页面,作为,认证成功显示的主窗体
8、编写LoginController,当用户没有登录时,会自动跳转到该控制器,然后转发到登录界面
@Controller
public class LoginController {
@RequestMapping("/login")
public String login(HttpServletRequest request) throws Exception {
//获得错误信息,判断 是没有登录,还是登录失败
String err = (String) request.getAttribute("shiroLoginFailure");
if(!StringUtils.isEmpty(err)){
//用户是因为登录失败进入的---抛出异常,由异常处理器进行捕获
//用户名不存在 UnknownAccountException
if(err.endsWith("UnknownAccountException")){
throw new Exception("用户名不存在");
}
//密码错误 IncorrectCredentialsException
if(err.endsWith("IncorrectCredentialsException")){
throw new Exception("密码错误");
}
}
//如果执行此处,表示,用户是没有登录进入
return "/login";
}
}
9、编写login.html
10、当点击登录按钮时,信息会提交到 AuthRealm类中认证的方法进行处理
11、认证成功以后,系统将会执行之前未执行的请求 FirstController进行处理
@RequestMapping("/")
public String first(HttpSession session){
System.out.println("-----进入控制器first---------");
//获得认证的主体
Subject subject = SecurityUtils.getSubject();
//从主体中获得用户信息
Object username = subject.getPrincipal();
session.setAttribute("username",username);
return "/main";
}
12、认证失败时,进入LoginController中,系统将抛出异常,所以要编写一个异常处理器,处理异常
<h1>出错了...</h1>
<h3>原因是:[[${err}]] </h3>
<hr>
<a th:href="@{/}">返回</a>
13、数据库的密码,一般都是加密后的密码,所以我们在认证的时候需要做加密处理
A、在配置类中,配置加密规则
@Bean
public AuthRealm authRealm(){
AuthRealm authRealm = new AuthRealm();
//指定,加密规则
authRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return authRealm;
}
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");//采用哪一种加密算法
hashedCredentialsMatcher.setHashIterations(3);//加密次数
return hashedCredentialsMatcher;
}
14、在realm类,在认证时,指定,采用的盐:
String salt="accp";
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal,pwd, ByteSource.Util.bytes(salt),"myRealm");
------@@@@@@@@@到此,认证成功,下面就开始授权--------------------------------------------------------------------------------------------------------
@@@@@@@@授权操作
在页面中,可以通过shirio标签进行权限判断
要使用shiro标签,要引入shiro的指令: xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"
<div shiro:hasPermission="user:add">
添加用户
</div>
@@@@@@@@@:注意,此时,如果直接使用标签,shiro进不去Realm类中授权的方法,必须要配置类中配置
一个对象才可以
要进行授权,必须在配置类,配置如下代码:
@Bean
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
在shiro加入缓存,缓存用户权限,避免频繁访问数据库
我们使用的缓存技术是: ehcache
1、将ehcache.xml文件导入到 resources/config目录中
2、在ShiroConfig配置类中,配置缓存
@Bean
public EhCacheManager ehCacheManager(){
EhCacheManager ehCacheManager = new EhCacheManager();
ehCacheManager.setCacheManagerConfigFile("classpath:conf/shiro-ehcache.xml");
return ehCacheManager;
}
3、在SecurityManager引用缓存管理
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//在安全管理器中,注入realm
securityManager.setRealm(authRealm());
//引用EhcacheManager
securityManager.setCacheManager(ehCacheManager());
return securityManager;
}