springboot-shiro chapter03 login
简介:这一节主要是集成shiro进行鉴权, 用户登录/退出
环境:
IDEA15+
JDK1.8+
Maven3+
代码:
https://git.oschina.net/xinshu/springboot-shiro
一、shiro 基本功能

Authentication:身份认证,验证用户身份;
Authorization:授权,验证某个已认证的用户是否拥有某个权限;如:验证某个用户是否拥有某个角色。或者验证某个用户对某资源是否具有某个权限;
Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;
Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
Web Support:Web支持,可以非常容易的集成到Web环境;
Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
Testing:提供测试支持;
Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
二、shiro 流程及基本概念

Shiro的对外API核心就是Subject;
Subject:主体,代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject;即一个抽象概念;所有Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager;SecurityManager才是实际的执行者;
SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject;可以看出它是Shiro的核心,它负责与后边介绍的其他组件进行交互,如果学习过SpringMVC,你可以把它看成DispatcherServlet前端控制器;
Realm:Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。
一个简单的Shiro应用:
1、应用代码通过Subject来进行认证和授权,而Subject又委托给SecurityManager;
2、需要给Shiro的SecurityManager注入Realm,从而让SecurityManager能得到合法的用户及其权限进行判断。
三、shiro Authentication认证特点
Authentication is the process of identity verification– you are trying to verify a user is who they say they are. To do so, a user needs to provide some sort of proof of identity that your system understands and trusts.
The Shiro framework is designed to make authentication as clean and intuitive as possible while providing a rich set of features. Below is a highlight of the Shiro authentication features.
Subject Based - Almost everything you do in Shiro is based on the currently executing user, called a Subject. And you can easily retrieve the Subject anywhere in your code. This makes it easier for you to understand and work with Shiro in your applications.
Single Method call - The authentication process is a single method call. Needing only one method call keeps the API simple and your application code clean, saving you time and effort.
Rich Exception Hierarchy - Shiro offers a rich exception hierarchy to offered detailed explanations for why a login failed. The hierarchy can help you more easily diagnose code bugs or customer services issues related to authentication. In addition, the richness can help you create more complex authentication functionality if needed.
‘Remember Me’ built in - Standard in the Shiro API is the ability to remember your users if they return to your application. You can offer a better user experience to your them with minimal development effort.
Pluggable data sources - Shiro uses pluggable data access objects (DAOs), called Realms, to connect to security data sources like LDAP and Active Directory. To help you avoid building and maintaining integrations yourself, Shiro provides out-of-the-box realms for popular data sources like LDAP, Active Directory, and JDBC. If needed, you can also create your own realms to support specific functionality not included in the basic realms.
Login with one or more realms - Using Shiro, you can easily authenticate a user against one or more realms and return one unified view of their identity. In addition, you can customize the authentication process with Shiro’s notion of an authentication strategy. The strategies can be setup in configuration files so changes don’t require source code modifications– reducing complexity and maintenance effort.
四、依赖资源
与上一节相比,这里主要依赖shiro-spring构建,由于shiro-spring构建又依赖于shiro-core及shiro-web控件,所以pom.xml文件只需依赖shiro-spring即可
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
五、配置及实现
从Shiro工作流程中,我们需要配置SecurityManager(负责接收Subject校验请求、与其他组件交互)及Reaml(获取安全数据信息)。由于是用spring-boot, 这里推荐由配置传统的xml文件改为java 注解@Configuration方式配置,主要配置如下:
@Configuration
public class ShiroConfiguration { private static Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); @Bean(name = "ShiroRealmImpl")
public ShiroRealmImpl getShiroRealm() {
return new ShiroRealmImpl();
} @Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager() {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(getShiroRealm());
return defaultWebSecurityManager;
} @Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
} @Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean() { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager()); shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setSuccessUrl("/welcome");
filterChainDefinitionMap.put("/welcome", "authc");
filterChainDefinitionMap.put("/**", "anon"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
}
其中:
Spring中使用shiro时, Spring容器会根据bean名称查找shiroFilter的bean,同时将所有Filter操作委托给它,shiroFilter作为入口定义了需要控制的URL规则类型,然后根据URL规则进行相应的安全控制,具体shiroFilter定义过程如下:
1.Spring中定义了一类特殊的Bean——FactoryBean,当需要“shiroFilter”的bean时, 会调用ShiroFilterFactoryBean的getObject()方法来实现

很显然ShiroFilterFactoryBean定义过程中需要指定Securitymanager, successUrl, loginUrl以及filterChainDefinitionMap等。
2.定义securityManager bean, 指定securitymanager类型,同时设置安全数据的获取方式setRealm(Realm realm)
3.定义Realm的bean,ShiroRealmImpl类具体实现如下:
public class ShiroRealmImpl extends AuthenticatingRealm {
private static Logger logger = LoggerFactory.getLogger(ShiroRealmImpl.class);
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
String username = usernamePasswordToken.getUsername();
String encodedPassword = new Sha256Hash(usernamePasswordToken.getPassword()).toBase64();
logger.info("------------------------authentication--------------------------");
if (false) {
// TODO 用户名不存在
throw new UnknownAccountException();
} else if (false) {
// TODO 密码错误
throw new IncorrectCredentialsException();
}
return new SimpleAuthenticationInfo(new ShiroUser(username, "用户编码", "用户名称"),
String.valueOf(usernamePasswordToken.getPassword()),
ByteSource.Util.bytes("用户id"), getName());
}
}
主要是实现了doGetAuthenticationInfo(AuthenticationToken token)方法,来验证当前用户身份信息
4.另外值得说明的是这里定义了,lifecycleBeanPostProcessor Bean这里主要的目的是管理shiro的生命周期
5.Spring mvc 登录/退出Controller,
请求/login时, http谓语为GET类型则加载login.jsp页面,POST类型作为验证用户身份的请求,调用subject.login(usernamePasswordToken)成功重定向到welcome.jsp, 否则重定向到login.jsp页面
@Controller
public class LoginController {
private static Logger logger = LoggerFactory.getLogger(LoginController.class); @Value(value = "${application.message}")
private String message; @RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginInit(Map<String, Object> model) {
return "login";
} @RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(Map<String, Object> model, @RequestParam("userid") String userId,
@RequestParam("password") String password) { UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userId, password); Subject subject = SecurityUtils.getSubject();
try {
subject.login(usernamePasswordToken);
} catch (UnknownAccountException uae) {
logger.info("未知账户");
} catch (IncorrectCredentialsException ice) {
logger.info("密码不正确");
} catch (LockedAccountException lae) {
logger.info("账户已锁定");
} catch (ExcessiveAttemptsException eae) {
logger.info("用户名密码次数过多");
} catch (AuthenticationException ae) {
logger.info("用户名密码不正确");
} if (subject.isAuthenticated()) {
logger.info("登录认证通过");
model.put("time", new Date());
model.put("message", this.message);
return "redirect:/welcome";
} else {
usernamePasswordToken.clear();
return "redirct:/login";
}
} @RequestMapping(value="/logout", method=RequestMethod.POST)
public String logout(){
SecurityUtils.getSubject().logout();
return "redirect:/login";
}
}
springboot-shiro chapter03 login的更多相关文章
- springboot + shiro + cas4.2.7 实战
1. 下载地址 https://github.com/apereo/cas/archive/v4.2.7.zip 2. 解压后, 用intellj idea 打开 3. 执行 gradle build ...
- springboot+shiro
作者:纯洁的微笑 出处:http://www.ityouknow.com/ 这篇文章我们来学习如何使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公 ...
- SpringBoot+Shiro+Redis共享Session入门小栗子
在单机版的Springboot+Shiro的基础上,这次实现共享Session. 这里没有自己写RedisManager.SessionDAO.用的 crazycake 写的开源插件 pom.xml ...
- SpringBoot+Shiro入门小栗子
写一个不花里胡哨的纯粹的Springboot+Shiro的入门小栗子 效果如图: 首页:有登录注册 先注册一个,然后登陆 登录,成功自动跳转到home页 home页:通过认证之后才可以进 代码部分: ...
- springboot+shiro+redis(单机redis版)整合教程-续(添加动态角色权限控制)
相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(单机redis版)整合教程 3. springboot+shiro+redis(集群re ...
- Spring Cloud之路:(七)SpringBoot+Shiro实现登录认证和权限管理
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sage_wang/article/details/79592269一.Shiro介绍1.Shiro是 ...
- springboot+shiro+redis(集群redis版)整合教程
相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(单机redis版)整合教程 3.springboot+shiro+redis(单机red ...
- springboot+shiro+redis(单机redis版)整合教程
相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(集群redis版)整合教程 3.springboot+shiro+redis(单机red ...
- springboot+shiro整合教程
进阶教程: 1. springboot+shiro+redis(单机redis版)整合教程 2. springboot+shiro+redis(集群redis版)整合教程 3.springboot+s ...
- springboot + shiro + mysql + mybatis 工程快速搭建
1. 新建 springboot 工程 2. 随便起个名字 3. 初始化工程 4. 导入 shiro 和 thymeleaf 依赖 <!-- thymeleaf依赖 --> <dep ...
随机推荐
- iPhone开发资源汇总
如何用Facebook graphic api上传视频: http://developers.facebook.com/blog/post/532/ Keychain保存数据封装: https://g ...
- 删除rz上传失败乱码的文件
[摘要:经过rz上传文件失利时,会发生巨细为0的治码的文件,以下 ls-l -rw-rr1rootroot4703112-1513:48???.htm 这类范例的文件可用以下敕令 find.-maxd ...
- js之3D轮播图
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Redis学习总结之一——Redis初入
Redis简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API. Redis是一个key-value存储系统. ...
- BZOJ4818 LOJ2002 SDOI2017 序列计数 【矩阵快速幂优化DP】*
BZOJ4818 LOJ2002 SDOI2017 序列计数 Description Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数. Alice还希 ...
- WPF 使用 WindowChrome,在自定义窗口标题栏的同时最大程度保留原生窗口样式(类似 UWP/Chrome)
WPF 自定义窗口样式有多种方式,不过基本核心实现都是在修改 Win32 窗口样式.然而,Windows 上的应用就应该有 Windows 应用的样子嘛,在保证自定义的同时也能与其他窗口样式保持一致当 ...
- vs中无法找到头文件
在VS项目上右键属性 C/C++->常规->附加包含目录中把此路径添加上,路径与路径之间用 ; 隔开
- mock的使用二(根据数据模板生成模拟数据)
Mock.mock( rurl?, rtype?, template|function( options ) ) 根据数据模板生成模拟数据. Mock.mock( template ) 根据数据模板生 ...
- 含锂电池的 PCBA 运输快递时如何包装?
含锂电池的 PCBA 运输快递时如何包装? PCBA 和电池必须固定. PCBA 和电池必须独立包装. 独立包装的外壳必须为硬包装,防止运输中挤压导致短路. 电池电量在 80% 或以下.
- (转)完美解决 Android WebView 文本框获取焦点后自动放大有关问题
完美解决 Android WebView 文本框获取焦点后自动放大问题 前几天在写一个项目时,要求在项目中嵌入一个WebView 本来很快就完成了,测试也没有问题.但发给新加坡时,他们测试都会出现文本 ...