当前位置: 首页 > 工具软件 > ICETutorial > 使用案例 >

Apache Shiro Tutorial 简单构建一个shiro应用

梁丘琛
2023-12-01

Apache Shiro Tutorial

第一个shiro应用

使用ini配置文件代表用户分组、密码、权限

slf4j+log4j日志输出

加载配置

public static void main(String[] args) {

    log.info("My First Apache Shiro Application");

    //1.
    Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");

    //2.
    SecurityManager securityManager = factory.getInstance();

    //3.
    SecurityUtils.setSecurityManager(securityManager);

    System.exit(0);
}

使用shiro进行验证和授权访问

subject代表用户

官方描述:

a security-specific view of the currently executing user

更加广泛,并不一定指人也可以是第三方平台进程、定时任务、守护进程或任何类似的东西

It simply means ‘the thing that is currently interacting with the software’.

基本上在所有环境中都可以通过

Subject currentUser = SecurityUtils.getSubject();

来获取当前用户

getSubject会获取当前线程中保存的用户信息(是根据现成的threadlocal来获取的

page request session application

web应用中代表一次请求request(还是一次session?

it acquires the Subject based on user data associated with current thread or incoming request.

多半是request

在程序运行时可获取当前用户与应用程序的会话 (session)无需在web环境中也可以获取(shiro的内置session?)

这里的Session代表shiro内置的,可以实现大部分HttpSession的功能并且有些额外的自己的功能

shiro自动识别不同环境,在web应用程序中使用基于HttpSession,在非web环境中提供shiro自己的企业级session管理器,可以在不同的应用中使用相同API

subject结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Svau2OhJ-1599285040726)(D:\Learning\shiro\Apache Shiro Tutorial.assets\image-20200829160102948.png)]

根据不同的subject环境获取session

获取subject就可以检查角色及其权限

检查用户是否登录,没登陆就获取用户名密码进行登录验证

if ( !currentUser.isAuthenticated() ) {
    //collect user principals and credentials in a gui specific manner
    //such as username/password html form, X509 certificate, OpenID, etc.
    //We'll use the username/password example here since it is the most common.
    UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");

    //this is all you have to do to support 'remember me' (no config - built in!):
    token.setRememberMe(true);

    currentUser.login(token);
}

通过丰富的验证示范exception

来支持您根据发生的不同情况进行处理做出反应

try {
    currentUser.login( token );
    //if no exception, that's it, we're done!
} catch ( UnknownAccountException uae ) {
    //username wasn't in the system, show them an error message?
} catch ( IncorrectCredentialsException ice ) {
    //password didn't match, try again?
} catch ( LockedAccountException lae ) {
    //account for that username is locked - can't login.  Show them a message?
}
    ... more types exceptions to check if you want ...
} catch ( AuthenticationException ae ) {
    //unexpected condition - error?
}
// shiro登录
Subject currentUser = SecurityUtils.getSubject();
AuthToken token = new AuthToken(JSONObject.toJSONString(staffInfo));
String cSession;
try {
    currentUser.login(token);
    // 设置登录用户信息缓存
    Session session = currentUser.getSession();
    cSession = session.getId().toString();
} catch (UnknownAccountException e) {
    throw new CheckResultException(ErrMsg.NO_ACCOUNT);
} catch (IncorrectCredentialsException e) {
    throw new CheckResultException(ErrMsg.INVALID_ACCOUNT_PASS);
}

登录后调用自己实现的realm的逻辑去验证登录

NoPassRealm->doGetAuthenticationInfo

登录后可以进行角色验证和权限验证然后登出

//say who they are:
//print their identifying principal (in this case, a username):
log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

//test a role:
if (currentUser.hasRole("schwartz")) {
    log.info("May the Schwartz be with you!");
} else {
    log.info("Hello, mere mortal.");
}

//test a typed permission (not instance-level)
if (currentUser.isPermitted("lightsaber:wield")) {
    log.info("You may use a lightsaber ring.  Use it wisely.");
} else {
    log.info("Sorry, lightsaber rings are for schwartz masters only.");
}

//a (very powerful) Instance Level permission:
if (currentUser.isPermitted("winnebago:drive:eagle5")) {
    log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
            "Here are the keys - have fun!");
} else {
    log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}

//all done - log out!
currentUser.logout();

小结

通过这个例子了解了如何在应用中使用shiro,shiro的主要设计意图,subject和securitymanager

这个应用很简单,如果不用INI而用复杂数据源(例如数据库)怎么办?

就需要接下去了解更深入的shiro架构以及配置机制。下一章

https://shiro.apache.org/architecture.html

Authentication特性

Authentication是识别认证的过程,例如你将验证一位用户是否是他们自己所描述的那位用户。

为此,用户需要提供系统可以理解和信任的某种身份证明。

Shiro框架旨在使身份验证尽可能干净和直观,同时提供丰富的功能。

  • 基于Subject(客体)

    在shiro中所作的几乎所有操作都基于当前用户,称为一个课题。你能简单在任何代码找到Subject。这使得它更易于让你在应用中使用和理解shiro。

  • 单一方法调用

    验证过程是一个简单的单一的方法调用,只需要一个方法调用是的API和你的英语代码简洁节约时间更加高效

  • 丰富的报错层次

    shiro提供了一个丰富的报错层次结构来提供在登录失败时的报错异常。层次结构能帮你更加简单的诊断代码bug或客户关于登录验证服务的问题。另外如果需要丰富性还能帮你创建更复杂的验证方法。

  • 记住我

    shiro中的标准能够在你的用户返回应用的时候记住他们。你能以最小的工作量提供更好的用户体验。

  • 可插拔的数据源

    shori使用可插拔的数据访问对象(data access objects,DAOs),被称为Realms,来安全的链接数据源类似LDAP或者Active Diectory,JDBC。如果有需要你能创建自己的Realm来支持在基础Realm之外的特殊功能。

  • 使用一个或多个数据源登录

    使用Shiro,你能简单的验证一个用户违反一个或一些realms返回一个验证其身份的统一视图。另外你能使用shiro身份验证策略概念来定义自己的验证过程

Authorization特性

Authorization(授权) ,也被称为访问控制,是一个应用程序中确定某个资源是否有访问权限的过程。换句话来说决定谁能访问它。授权用于回答类似是否用户能编辑账户、用户是否能访问网页,是否用户能点击这个按钮之类的安全问题。这些都是决定一个用户是否有权访问的检查。

Authorization授权是任何应用程序的关键要素,但它很快就会变得非常复杂。 Shiro的目标是消除授权方面的许多复杂性,以便您可以更轻松地构建安全软件。 下面是Shiro授权功能的重点。

  • 基于Subject
  • 基于角色和权限的检查
  • 强大而只管的权限语法
  • 多种强力操作
  • 强大的缓存支持
  • 可插拔数据源
  • 支持数据模型

原文 https://shiro.apache.org/tutorial.html

 类似资料: