小Hub领读:

导入jar包,配置yml参数,编写ShiroConfig定义DefaultWebSecurityManager,重写Realm,编写controller,编写页面,一气呵成。搞定,是个高手~


上面一篇文章中,我们已经知道了shiro的认证与授权过程,这也是shiro里面最核心常用的基础功能。现在我们把shiro集成到我们的项目中,开始搭建一个有认证和权限体系的项目,比如用户中心需要登录之后才能访问等!

1、极简入门,Shiro的认证与授权流程解析

集成Shiro

根据官方文档: https://shiro.apache.org/spring-boot.html

第一步:集成导入jar包:

org.apache.shiro

shiro-spring-boot-web-starter

1.4.2

有些同学还在用 shiro-spring的jar包,但是集成的配置就相对多一点,所以可以直接使用starter包更加方便。

第二步:写好配置,官方给我们提供的属性参数,以及一些默认值,如果不符合我们的需求,可以自行改动哈。

从配置上就可以看出,shiro的注解功能,rememberMe等功能已近自动集成进来了。所以starter包使用起来还是非常简单的,只需要熟悉shiro的流程,从0开发不在话下哈。

  • application.yml

shiro:

web:

enabled: true

loginUrl: /login

spring:

freemarker:

suffix: .ftl # 注意新版本后缀是 .ftlh

template-loader-path: classpath:/templates/

settings:

classic_compatible: true #处理空值

上面的配置,我就改了一下登录的url,其他都是使用默认的,作为我们最简单的测试,相信你们。

第三步:配置shiro的securityManager和自定义realm。因为realm负责我们的认证与授权,所以是必须的,自定义的realm必须要交给securityManager管理,所以这两个类需要重写。然后还有一些资源的权限说明,所以一般需要定义ShiroFilterChainDefinition,所以有3个类我们常写的:

  • AuthorizingRealm

  • DefaultWebSecurityManager shiro的核心管理器

  • ShiroFilterChainDefinition 过滤器链配置

@Configuration

public class ShiroConfig {

@Bean

AccountRealm accountRealm() {

return new AccountRealm();

}

@Bean

public DefaultWebSecurityManager securityManager(AccountRealm accountRealm) {

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

securityManager.setRealm(accountRealm);

return securityManager;

}

@Bean

public ShiroFilterChainDefinition shiroFilterChainDefinition() {

DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();

// logged in users with the 'admin' role

chainDefinition.addPathDefinition("/admin/**", "authc, roles[admin]");

// logged in users with the 'document:read' permission

chainDefinition.addPathDefinition("/docs/**", "authc, perms[document:read]");

chainDefinition.addPathDefinition("/login", "anon");

chainDefinition.addPathDefinition("/doLogin", "anon");

// all other paths require a logged in user

chainDefinition.addPathDefinition("/**", "authc");

return chainDefinition;

}

}

上面说到ShiroFilterChainDefinition是定义过滤器配置的,啥意思呢,我们来看看其中一句:

chainDefinition.addPathDefinition("/admin/**", "authc, roles[admin]");

这一句代码意思是说:访问 /admin/**开头的链接,都需要已经完成登录认证 authc、并且拥有 admin角色权限才能访问。

你可以看到key-value是 链接-过滤器的组合,过滤器可以同时多个。那么authc、role、perms、anon到底是哪来的呢?有啥特殊意义?是啥拦截器?

我们来看下这个说明文档:

可以看到,其实每个简写单词,都是一个过滤器的名称。比如authc代表这 FormAuthenticationFilter。每个过滤器具体是啥用的?我们看几个常用的吧:

  • authc 基于表单的拦截器,没有登录会跳到相应的登录页面登录

  • user 用户拦截器,用户已经身份验证 / 记住我登录的都可

  • anon 匿名拦截器,即不需要登录即可访问

  • roles 角色授权拦截器,验证用户是否拥有所有角色

  • perms 权限授权拦截器,验证用户是否拥有所有权限

第四步:ok,根据需求项目的资源制定项目过滤器链 ShiroFilterChainDefinition。我们再回到AccountRealm这个类。我们之前说过,认证授权的过程,我们是在Realm里面完成的。所以我们需要继承Realm,并实现两个方法。

但是这里需要注意,我们一般不直接继承 Realm,可以看看Realm接口:

  • org.apache.shiro.realm.Realm

public interface Realm {

String getName();

boolean supports(AuthenticationToken token);

AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;

}

而从上一篇文章中,我们分析的认证授权的源码过程时候,你会看到,认证和授权分别调用的realm是 AuthenticatingRealm和 AuthorizingRealm。说明源码里面已经经过了一些封装,所以我们就不能再直接继承 Realm,那么 AuthenticatingRealm和 AuthorizingRealm我们继承哪个呢?我们发现 AuthorizingRealm是继承 AuthenticatingRealm的,所以在重写realm的时候,我们只需要集成超类 AuthorizingRealm即可。

public abstract class AuthorizingRealm extends AuthenticatingRealm

所以,结合了授权与验证,还有缓存功能,我们自定义Realm的时候继承AuthorizingRealm即可。

  • com.markerhub.shiro.AccountRealm

public class AccountRealm extends AuthorizingRealm {

@Autowired

UserService userService;

/**

* 授权方法

*/

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

AccountProfile principal = (AccountProfile) principalCollection.getPrimaryPrincipal();

// 硬编码(赋予用户权限或角色)

if(principal.getUsername().equals("MarkerHub")){

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

info.addRole("admin");

return info;

}

return null;

}

/**

* 认证方法

*/

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

AccountProfile profile = userService.login(token.getUsername(), String.valueOf(token.getPassword()));

// 把用户信息存到session中,方便前端展示

SecurityUtils.getSubject().getSession().setAttribute("profile", profile);

SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(profile, token.getCredentials(), getName());

return info;

}

}

  • com.markerhub.service.impl.UserServiceImpl

@Service

public class UserServiceImpl implements UserService {

@Override

public AccountProfile login(String username, String password) {

//TODO 查库,然后匹配密码是否正确!

if(!"MarkerHub".equals(username)) {

// 抛出shiro异常,方便通知用户登录错误信息

throw new UnknownAccountException("用户不存在");

}

if(!"111111".equals(password)) {

throw new IncorrectCredentialsException("密码错误");

}

AccountProfile profile = new AccountProfile();

profile.setId(1L);

profile.setUsername("MarkerHub");

profile.setSign("欢迎关注公众号MarkerHub哈");

return profile;

}

}

上面代码中,我login方法直接给出了账号MarkerHub,并赋予了角色admin。

第五步:ok,准备动作已经热身完毕,接下来我们去编写登录、退出接口,以及我们的界面:

  • com.markerhub.controller.IndexController

@Controller

public class IndexController {

@Autowired

HttpServletRequest req;

@RequestMapping({"/", "/index"})

public String index() {

System.out.println("已登录,正在访问!!");

return "index";

}

@GetMapping("/login")

public String login() {

return "login";

}

/**

* 登录

*/

@PostMapping("/doLogin")

public String doLogin(String username, String password) {

UsernamePasswordToken token = new UsernamePasswordToken(username, password);

try {

SecurityUtils.getSubject().login(token);

} catch (AuthenticationException e) {

if (e instanceof UnknownAccountException) {

req.setAttribute("errorMess", "用户不存在");

} else if (e instanceof LockedAccountException) {

req.setAttribute("errorMess", "用户被禁用");

} else if (e instanceof IncorrectCredentialsException) {

req.setAttribute("errorMess", "密码错误");

} else {

req.setAttribute("errorMess", "用户认证失败");

}

return "/login";

}

return "redirect:/";

}

/**

* 退出登录

*/

@GetMapping("/logout")

public String logout() {

SecurityUtils.getSubject().logout();

return "redirect:/login";

}

}

第六步:登录页面:

  • templates/login.ftl

lang="en">

charset="utf-8"/>

MarkerHub 登录

用户登录欢迎关注公众号:MarkerHub

method="post" action="/doLogin">

username: name="username" type="text">

password: name="password" type="password">

type="submit" name="提交">

style="color: red;">${errorMess}

登录成功页面:

  • templates/index.ftl

登录成功:${profile.username}${profile.sign}

href="/logout">退出

ok,代码我们已经编写完成,接下来,我们运行项目,然后访问首页,将自行跳转到登录页面,然后输入账号密码之后,我们可以看到完成登录!

登录界面:

登录成功页面:

结束语

好了,今天做了一个极简的登录注册功能,介绍了一下shiro的基本整合步骤。流程还是挺简单的哈哈,不知道你看懂了没。

而在一些负载均衡的场景中,我们的会话信息是需要共享的,所以shiro一般会和redis整合在一起,你知道怎么整合吗?我们明天再聊哈,记得来哦,MarkerHub每天发文时间19点20分。

附:demo git源码地址:https://github.com/MarkerHub/JavaDemo/tree/master/整合示例/springboot-shiro-demo


(完)

MarkerHub文章索引:

https://github.com/MarkerHub/JavaIndex

【推荐阅读】

eblog项目讲解视频上线啦,长达17个小时!!

SpringBoot整合redisson实现分布式锁

极简入门,Shiro的认证与授权流程解析

面试官: HashMap 为什么线程不安全?

Spring cache整合Redis,并给它一个过期时间!

好文!必须点赞

apache shiro jar包_只需要6个步骤,springboot集成shiro,并完成登录相关推荐

  1. gradle 项目打包成多个jar包_永不失优雅——高效管理Springboot项目

    猿灯塔 全文略长 希望能帮到各位 另外!文末有你们想要的白嫖惊喜哦! 本文主要讲述一下如何优雅地管理SpringBoot项目. 第一种方式:使用SHELL脚本 As we known 作为一个后端程序 ...

  2. shiro jar包下载

    shiro是一款java安全框架,使用shiro jar包可以执行身份验证,授权,密码学和会话管理功能,如果想使用shiro这款安全框架就马上下载shiro jar包进行使用吧. 基本简介 shiro ...

  3. java org.apache.http_org.apache.http jar包下载-org.apache.http.jar包下载 --pc6下载站

    org.apache.http.jar包是一款十分常用的jar包如果没有org.apache.http.jar包Apache与http的链接将会出现错误等现象马上下载org.apache.http.j ...

  4. SpringBoot集成Shiro安全框架

    SpringBoot集成Shiro安全框架 1.shiro的定义 2.SpringBoot集成shiro的步骤 3.完成的效果 1.shiro的定义 1.shiro的作用 认证.授权.加密.会话管理. ...

  5. springboot集成shiro实现用户登录认证

    Apache Shiro 是一个功能强大且易于使用的Java安全框架,可执行身份验证.授权.加密和会话管理.使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移动应用程序到最大 ...

  6. springboot集成shiro 前后端分离 统一处理shiro异常

    springboot集成shiro 前后端分离 统一处理shiro异常 参考文章: (1)springboot集成shiro 前后端分离 统一处理shiro异常 (2)https://www.cnbl ...

  7. k8s部署jar包_学习K8S之路.6--- 在K8S中部署Jenkins,并使用Jenkins打包jar包

    一:部署jenkins jenkins官网:https://jenkins.io/download/ jenkins镜像:https://hub.docker.com/r/jenkins/jenkin ...

  8. hibernate jar包_源码分析 | 咋嘞?你的IDEA过期了吧!加个Jar包就破解了为什么?

    推荐阅读: 阿里P8架构师"呕心沥血"1年总结出这份Linux基础到进阶学习文档 年前面试京东3面凉经~ 面试过程与真题全分享+备战春招(java) 一.前言介绍 2020年了,对 ...

  9. sql server jar包_老王,怎么完整SQL的显示日志,而不是???...

    点击蓝色"Java面试那些事儿"关注我哟 加个"星标",优质文章,第一时间送达 来源:http://1t.click/ag6q在常规项目的开发中可能最容易出问题 ...

最新文章

  1. Anaconda中安装Orange3脚本-完整版
  2. 安装cv2(opencv-python)遇到的问题
  3. 拐点已至,云原生引领数字化转型升级
  4. 【推荐】让你事半功倍的交互体验自查清单
  5. sublime text 3 前端开发常用插件
  6. Bokeh——交互式可视化库
  7. Python练习:合格率的计算
  8. opencv之imread()
  9. 御剑后台扫描工具下载、安装、使用教程
  10. 全球DEM下载 90米、30米、12.5米等各种精度DEM数据
  11. 3D人体姿态估计总结
  12. 旋转木马图片效果图,轮播图
  13. vue 页脚_如何将页脚固定在页面底部_sticky footer, Layout, templates, 会员专栏 教程_w3cplus...
  14. Python 3 《Class》入门练习
  15. 扑克迷如何在2019-03-28的市场中利用十字星进行跑赢大盘
  16. matlab高程数据点,matlab 对tif数据高程图的处理分析
  17. Schnorr signature (Schnorr 签名)数学原理
  18. 菲尔兹奖得主丘成桐院士:数学之美与应用
  19. ModelSim 实用知识:优化,SDF,覆盖率
  20. 访问学者申请德国签证如果丢失了怎么办?

热门文章

  1. python二维数组怎么写_python的二维数组操作
  2. 如何将本地项目发布到gitee?
  3. Python之 jinja2模板浅析
  4. linux中时间戳与date的互转
  5. 循环中 动态参数 传div 层_【转载】黄学杰等:铌元素在锂离子电池中的应用
  6. hive 安装_7.Hive介绍以及安装
  7. python3代码转python2_Python2代码转成Python3代码
  8. 计算机考研择校分析,上海地区计算机考研择校分析
  9. Linux中look命令,如何在Linux上使用look命令 | MOS86
  10. 3d饼图 vue_这是我见过最优雅的Vue图片轮播插件——Vue-Awesome-Swiper