1.shiro的简介
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
主要功能
三个核心组件:Subject, SecurityManager 和 Realms.
Subject:
即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。
Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager:
它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
Realm:
Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。
2.shiro基本配置
1.pom.xml配置,引入shiro坐标。
</dependency>
<!--引入shiro安全框架-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
2.添加两个配置类(UserRealm.java,ShiroConfig.java)
UserRealm.java
package alian.config;
import org.apache.catalina.realm.AuthenticatedUserRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
public class UserRealm extends AuthorizingRealm{
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
// TODO Auto-generated method stub
System.out.println("执行授权逻辑");
/*
*
* 此步骤可以查询用户的权限,在配置用户的权限即可
*
*
* */
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
info.addStringPermission("user:add");
// 添加user:add权限
// 此操作可以获取认证存入的信息
// Subject subject=SecurityUtils.getSubject();
// subject.getPrincipal();
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
// TODO Auto-generated method stub
System.out.println("执行认证逻辑");
String name="alian";
String password="12345";
UsernamePasswordToken token=(UsernamePasswordToken) arg0;
if(!token.getUsername().equals(name))
{
return null;
}
return new SimpleAuthenticationInfo("",password, "");
/*
* 可以传递查询的用户进去,在授权的过程中可以拿到用户登录信息
* new SimpleAuthenticationInfo(user,password, "");
*
*
* */
}
}
ShiroConfig.java
package alian.config;
import java.util.HashMap;
import java.util.Map;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
@Configuration
public class ShiroConfig {
// 1.创建ShiroFilterFactoryBean
@Bean()
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("DefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager)
{
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
// 设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
// 添加shiro内置过滤器
/*
*
* shiro内置过滤器
* 常用过滤器
* anon:无需认证
* authc:必须认证才可以访问
* user:如果使用rememberMe的功能可以直接访问
* perms:该资源必须得到资源权限才可以访问
* role:该资源必须得到角色权限才可以访问
*
* */
Map<String,String> filterMap=new HashMap<String, String>();
filterMap.put("/index","authc");
filterMap.put("/login","anon");
filterMap.put("/UnauthorizedUrl","anon");
// filterMap.put("/user/**","authc");
filterMap.put("/user/add","perms[user:add]");
filterMap.put("/user/del","perms[user:del]");
// 进行资源的权限访问
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
shiroFilterFactoryBean.setLoginUrl("/tologin");
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorizedUrl");
// 设置登录请求路径
return shiroFilterFactoryBean;
}
// 2.创建DefaultWebSecurityManager
@Bean("DefaultWebSecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("UserRealm") UserRealm realm)
{
DefaultWebSecurityManager defaultWebSecurityManager=new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
}
// 3.创建自定义Realm
@Bean("UserRealm")
public UserRealm getRealm()
{
return new UserRealm();
}
// shiro整合thymeleaf
/*
*
* <div shiro:hasPermission:"user:add">
* </div>
* 可以为不同权限显示不同页面
*
* */
@Bean()
public ShiroDialect getShiroDialect()
{
return new ShiroDialect();
}
}
详细的解释,代码段前面都有注解。
3.控制器TestController.java
package alian.controller;
import org.apache.catalina.security.SecurityUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class TestController {
@RequestMapping("/test")
public @ResponseBody Object test()
{
return "hello the world!";
}
@RequestMapping("/index")
public String index()
{
return "index";
}
@RequestMapping("/unauthorizedUrl")
public String unauthorizedUrl()
{
return "unauthorizedUrl";
}
@RequestMapping("/tologin")
public String tologin()
{
return "login";
}
@RequestMapping("/user/add")
public String add()
{
return "/user/add";
}
@RequestMapping("/user/del")
public String del()
{
return "/user/del";
}
@RequestMapping("/login")
public String login(String username,String password,Model model)
{
/*
*
* 使用shiro编写认证操作
*
* */
model.addAttribute("name", username);
// 1.获取subject
Subject subject=SecurityUtils.getSubject();
// 2.封装用户数据
UsernamePasswordToken token=new UsernamePasswordToken(username,password);
// 3.执行登录方法
try {
subject.login(token);
}
catch(UnknownAccountException e)
{
System.out.println("用户名错误");
return "login";
}
catch(IncorrectCredentialsException e)
{
System.out.println("密码错误");
return "login";
}
return "/index";
}
}
3.原理分析:
shiro基本分为两个功能,认证和授权,认证是指登录过程中检验是否为合法用户doGetAuthorizationInfo(),授权为合法用户分配不同级别的资源doGetAuthenticationInfo(),主要是AuthorizingRealm子类的功能。在ShiroFilterFactoryBean安全管理器负责分配路径url的权限,用于AuthorizingRealm子类去验证。
4.shiro的好处:
1.简单易懂,配置极为简单(和springsecurity)。
2.和thymeleaf整合,可以为不同权限的用户在视图层分配不同的页面资源。
3.安全性较高,对密码的加密。