安全框架Shiro------------------介绍与使用
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管理
谢谢阅读,如果有错误之处,请指出!
相关推荐
杜鲁门 2020-11-05
luckyxl0 2020-08-16
Dullonjiang 2020-08-09
xclxcl 2020-08-03
zmzmmf 2020-08-03
MicroBoy 2020-08-02
ganjing 2020-08-02
likesyour 2020-08-01
zmzmmf 2020-07-09
MicroBoy 2020-07-05
zzhao 2020-06-26
子云 2020-06-18
visionzheng 2020-06-07
neweastsun 2020-06-04
ErixHao 2020-06-03
GDreams0 2020-06-01
ganjing 2020-05-29
zmzmmf 2020-05-28
nullcy 2020-05-26