一:shiro是什么?
1.shiro是什么
shiro是apache开源组织开发的一套开源的安全(权限)框架,跨语言跨平台,能在B/S架构上运行,也能在C/S架构上运行。
2.shiro与传统权限的区别
shiro是对传统的五表权限进行了封装,shiro把用户的认证(登录)和授权(用户赋权限)功能进行了封装处理,使权限操作更加简便,shiro需要传统五表权限来维护用户 角色 权限之间的关系。
3.shiro的原理(运行流程)
securityManager 安全管理中心(shiro的所有操作都由它来完成)
Authenticator 认证 (登录)
Authorizer 授权(使用当前登录用户的id到数据库中查询用户所拥有的权限)
Realm 域 用来连接关系型数据库 执行对应的sql语句
Subject 主体 当前的登录用户 相当于五表权限中的session
认证流程:
二:SpringBoot微框架集成shiro完成登录拦截器功能。
认证流程:
1.首先在pom.xml配置文件中引入shiro所需要的jar包
<!--shiro所需要的jar包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
2.包结构下创建子包shiro,创建类为ShiroConfig
ShiroConfig:
package com.jk.shiro;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration//把当前类 作为spring配置文件使用
public class ShiroConfig {
/**
* shiro 的过滤器链
* shiro的核心总入口
*
* */
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
System.out.println("ShiroConfiguration.shirFilter()");
// shiro过滤器工厂
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager 如果不设置就无法完成认证和授权
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 过滤器链
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
// logout shiro定义好的过滤器名字 /logout访问路径
// 浏览器访问的地址栏路径中以/logout结尾的路径 走logout过滤器
// logout会清除session 退出登录
//第一个参数是前台发送的路径
filterChainDefinitionMap.put("/logout", "logout");
// 所有的css文件走 anon过滤器 此过滤器代表放过拦截 不需要权限也能访问
filterChainDefinitionMap.put("/css/**", "anon");
// 放过登录页面拦截
filterChainDefinitionMap.put("/toLogin", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
/// **代表所有路径 除以上路径外都拦截 authc代表权限拦截过滤器
filterChainDefinitionMap.put("/**", "authc");
// perms权限过滤器 必须拥有某项权限才能访问对应路径
// filterChainDefinitionMap.put("/add", "perms[user:query]");
// 登录请求路径 登录页面提交form表单时 表单的action写此路径
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功跳转到登录成功页面
shiroFilterFactoryBean.setSuccessUrl("/index");
// 未授权界面;
//shiroFilterFactoryBean.setUnauthorizedUrl("/warning");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
// 最终返回过滤器链
return shiroFilterFactoryBean;
}
@Bean // 在xml文件中配置一个bean标签 相当于<bean class="
// org.apache.shiro.mgt.SecurityManager"
// name="securityManager"></bean>
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm. 域(数据源 用来连接数据库完成认证和授权)
// 把自己创建的Realm 注入到securityManager中
securityManager.setRealm(myShiroRealm());
// 注入缓存管理器;
//securityManager.setCacheManager(ehCacheManager());//
// 这个如果执行多次,也是同样的一个对象;
// securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
@Bean
public MyRealm myShiroRealm(){
return new MyRealm();
}
}
3.接着在shiro包中手动创建realm,MyRealm类
package com.jk.shiro;
import com.jk.model.UserBean;
import com.jk.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
public class MyRealm extends AuthorizingRealm {
//注入Servie层
@Autowired
private UserService userService;
//认证方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取到输入框输入的用户名
String userName = (String)token.getPrincipal();
//去后台查是否有此账号
UserBean user = userService.queryUserByName(userName);
//判断账号是否存在
if(user == null){
//如果用户对象为空 抛出用户名错误异常
throw new UnknownAccountException();
}
//认证器 第一个参数为用户名或用户对象 第二个参数为密码 第三个参数为当前real名称
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName,user.getPassword(),this.getName());
return simpleAuthenticationInfo;
}
//授权方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
}
4.创建LoginController写自己的登录逻辑
package com.jk.controller;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
@Controller
public class LoginController {
/**
* 当用户名密码不正确时
* 跳转到此方法
* 认证失败之后会进入此方法 提示用户失败原因
* @return
*/
@RequestMapping("login")
public String login(HttpServletRequest request, ModelMap map){
//认证器会根据对应的错误 返回对应的异常 根据异常判断对应错误
String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
if(UnknownAccountException.class.getName().equals(exceptionClassName)
|| AuthenticationException.class.getName().equals(exceptionClassName)){
System.out.println("request = [ 用户名异常]");
map.put("message","用户名错误");
}else{
System.out.println("request = [密码异常]");
map.put("message","密码错误");
}
return "login";
}
@RequestMapping("toLogin")
public String toLogin(){
//登陆页面
return "login";
}
@RequestMapping("index")
public String toIndex(){
//主页面
return "main";
}
}
5.templates文件夹下创建login登录页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title>Insert title here</title>
</head>
<body>
<!--action="login" 写配置文件中的LoginUrl中内容 -->
<form action="login" method="post">
<!--username shiro默认的用户名属性 -->
<input type="text" name="username"/><br/>
<!--password shiro默认的密码属性 -->
<input type="password" name="password"/><br/>
<input type="submit" value="登录"/><br/>
</form>
</body>
</html>
6.访问http://localhost:8080(你的端口号)/tologin 完成登录
完毕!