Shiro介绍
Shiro是Apache下的一个开源项目,它是一个比较简单容易使用的安全框架,它提供了认证,授权,加密,会话管理等功能
Shiro三大核心组件
Subject: 可理解成是当前用户主体,所有的Subject都会被绑定到一个SecurityManager中,跟Subject交互实质就是跟SecurityManager交互SecurityManager: Shiro的核心,管理所有的Subject,它主要用于协调Shiro内部各种安全组件,可把它看成Shiro的管家
Realm: 可把它理解成是Shiro连接数据库的桥梁,无论Shiro进行认证还是授权都需要数据对比,而它就是Shiro去数据库拿数据的桥梁;改组件是由开发人员来写的,一般都是定义一个类继承AuthorizingRealm类,然后重写里面的方法
Shiro的常用用途
一般来说,我们使用Shiro都是用来进行认证,授权和会话(Session)管理
【认证】----------登陆的时候对用户的验证,如何验证是由开发人员来写的,会在Realm的认证方法中写对应的逻辑
【授权】----------对认证的用户进行赋予权限和角色,当某些方法访问需要权限和角色的时候就会触发验证,只有拥有对应的权限和角色才能进行访问,哪些方法访问需要权限或者角色也是由开发人员来规定的;
Shiro的简单使用
添加依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.2</version>
</dependency>
如果使用EhCache缓存的时候需要添加它的依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>>1.4.0</version>
</dependency>
自定义Realm
public class MyRealm extends AuthorizingRealm
{
//注意让自定义的Realm继承AuthorizingRealm类并重写它的认证,授权方法
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0)
{
String userId = ShiroUtils.getUserId(); //这是获取认证的用户的id,能进入改方法证明用户通过了认证
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 角色加入AuthorizationInfo认证对象
info.setRoles(参数是根据用户id从数据库中查出来的角色集合,Set集合来的);
// 权限加入AuthorizationInfo认证对象
info.setStringPermissions(参数是根据用户id从数据库中查出来的权限集合,Set集合来的);
return info;
}
/**
* 登录认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
{
//该对象是封装了用户账号更密码的一个对象,它是登陆那里记录的账号密码,不是从数据库查出来的账号密码
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String userId = upToken.getUsername();
String password = "";
if (upToken.getPassword() != null)
{
password = new String(upToken.getPassword());
}
Nurse user;
user = 根据用户账号去数据库查询; //这一步是根据账号去数据库查用户
if(user==null){
throw new UnknownAccountException("用户名或密码错误!"); //抛出异常
{
//注意这几个参数,前面两个都是使用数据库查出来的数据,不是使用从参数token中获取的数据
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
}
配置Shiro
@Configuration
public class ShiroConfig {
/**
* 自定义Realm
*/
@Bean
public MyRealm myRealm()
{
MyRealm myRealm = new MyRealm();
return myRealm;
}
/**
* 安全管理器
*/
@Bean
public SecurityManager securityManager(MyRealm myRealm)
{
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(userRealm);
return securityManager;
}
private LogoutFilter logoutFilter() { // 在ShiroFilterFactoryBean中使用
LogoutFilter logoutFilter = new LogoutFilter();
logoutFilter.setRedirectUrl("/login"); // 首页路径,登录注销后回到的页面
return logoutFilter;
}
/**
* 开启Shiro注解通知器,注意这个配置,如果没配置会导致注解无效
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
@Qualifier("securityManager") SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* Shiro过滤器配置
*/
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
{
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// Shiro的核心安全接口,这个属性是必须的
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 身份认证失败,则跳转到登录页面的配置
shiroFilterFactoryBean.setLoginUrl(路径);
// 权限认证失败,则跳转到指定页面
shiroFilterFactoryBean.setUnauthorizedUrl(路径);
// Shiro连接约束配置,即过滤链的定义
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 对静态资源设置匿名访问
filterChainDefinitionMap.put("/favicon.ico**", "anon");
filterChainDefinitionMap.put("/ruoyi.png**", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/docs/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
filterChainDefinitionMap.put("/image/**", "anon");
filterChainDefinitionMap.put("/ajax/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/plugins/**", "anon");
filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
// 不需要拦截的访问
filterChainDefinitionMap.put("/login", "anon");
Map<String, Filter> filters = new LinkedHashMap<>();
// 注销成功,则跳转到指定页面
filters.put("logout", logoutFilter());
shiroFilterFactoryBean.setFilters(filters);
// 所有请求需要认证
filterChainDefinitionMap.put("/**", "user");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
}
使用认证功能
/**
* 用户登录
*/
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(User user) {
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getName(), user.getPassword());
Subject subject = SecurityUtils.getSubject(); //获取shiro的实体对象
try {
// 登录操作
subject.login(usernamePasswordToken); //调用shiro中的认证方法对账号密码进行验证,这一行是重点,调用它才触发认证方法
User user = (UserInfo) subject.getPrincipal(); //获取shiro中认证的主体对象
return "index";
} catch (Exception e) {
return "login";
}
}
使用授权功能
/*
一定要注意,只有使用了shiro的那些注解,才能使用授权功能,才有权限角色验证之说
常用的几个注解:
@RequiresPermissions("权限")----------这是权限注解,当用户拥有该权限时才能进行访问
@RequiresRoles("角色")--------------这是角色注解,只有用户拥有该角色的时候才能进行访问
@RequiresAuthentication()----------示当前Subject已经通过login 进行了身份验证,没有验证就报异常
< shiro中的注解可以一起使用的 >
*/
--------使用例子:
/**
* 删除用户
*/
@RequiresPermissions("userInfo:del") //只有使用了shiro的注解才会触发授权验证效果,这是注解之一
@RequestMapping(value = "/del", method = RequestMethod.GET)
public String del() {
return "删除用户名 bobo 成功";
}
以上的Shiro只是简单的使用,没有添加Ehcache缓存和加密,没有使用记住我,也没有使用Session管理
谢谢阅读,如果有错误之处,请指出!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。