一、创建项目
执行tree ./src/main/java/
命令,查看项目。
./src/main/java/
└── javaboy
└── greamrod
├── DemoApplication.java
├── MainApp.java
├── entity
│ └── User.java
└── shiro
├── ShiroRealm.java
└── ShiroUtils.java
创建SpringBoot
项目,导入shiro-spring
的依赖包。
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
二、创建User
实体类
在javaboy.greamrod.entity
根包下,并创建User
实体类。
package javaboy.greamrod.entity;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String username;
private String password;
private Integer status; //0:正常、1:禁用、2:锁定
}
三、创建自定义的Realm
类
在javaboy.greamrod.shiro
根包下,并创建ShiroRealm
类。
提示:
doGetAuthenticationInfo()
方法中,可以修改User user = new User("zhangsan", "123", 2);
代码,测试认证方法的异常。
doGetAuthorizationInfo
方法中,可以修改info.addRoles();、info.addStringPermissions()
代码,来判断当前用户对某个资源是否有角色、权限。
package javaboy.greamrod.shiro;
/**
* 自定义的Realm
*/
public class ShiroRealm extends AuthorizingRealm {
/**
* 执行授权逻辑
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.err.println("-- 执行授权逻辑 --");
Object principal = principals.getPrimaryPrincipal();
System.err.println("principals >>> "+ principals);
System.err.println("principal >>> "+ principal);
//TODO 模拟根据`username`查询数据库中查询,指定`user` --> 角色、权限。
Collection<String> roles = new HashSet<>();
roles.add("admin");
roles.add("guest");
Collection<String> permissions = new HashSet<>();
permissions.add("product:view"); //查看产品列表
permissions.add("product:create"); //创建产品
permissions.add("product:edit"); //编辑产品
permissions.add("product:remove"); //删除产品
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addRoles(roles);
info.addStringPermissions(permissions);
return info;
}
/**
* 执行认证逻辑
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.err.println("-- 执行认证逻辑 --");
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
String username = token.getUsername();
String password = new String(token.getPassword());
System.err.println("username >>> "+ username);
System.err.println("password >>> "+ password);
//TODO 模拟根据`username`查询数据库中查询指定`user`记录。
User user = new User("zhangsan", "123", 0);
if (user == null) {
throw new UnknownAccountException("账户不存在异常!!!");
}else if (! user.getPassword().equals(password)) {
throw new CredentialsException("密码不存在异常!!!");
}else if (user.getStatus() == 1) {
throw new DisabledAccountException("用户被禁用异常!!!");
}else if(user.getStatus() == 2) {
throw new LockedAccountException("用户被锁定异常!!!");
}
String realName = getName();
Object principal = token.getPrincipal();
Object credentials = token.getCredentials();
System.err.println("realName >>> "+ realName);
System.err.println("principal >>> "+ principal); //username
System.err.println("credentials >>> "+ credentials.toString()); //password
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, realName);
return info;
}
}
四、搭建Shiro
安全管理框架
在javaboy.greamrod.shiro
根包下,创建ShiroUtils
类。该类提供了搭建shiro
框架方法、登录方法、登出方法。
package javaboy.greamrod.shiro;
public class ShiroUtils {
/**
* 搭建Shiro的框架
*/
public static void buildShiro() {
//创建自定义Realm对象
ShiroRealm realm = new ShiroRealm();
//创建SecurityManager安全管理器,并注入自定义的Realm
SecurityManager securityManager = new DefaultSecurityManager(realm);
//使用SecurityUtils将SecurityManager设置到运行环境中
SecurityUtils.setSecurityManager(securityManager);
}
/**
* 执行登录操作
* @param username 登录账号
* @param password 账号密码
*/
public static void login(String username, String password) {
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
subject.login(token);
}
/**
* 执行登出操作
*/
public static void logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
}
}
五、测试shiro
安全管理框架
在javaboy.greamrod
根包下,创建MainApp
类,并测试shiro
框架。
package javaboy.greamrod;
public class MainApp {
public static void main(String[] args) {
/**
* 1、搭建Shiro框架
*/
ShiroUtils.buildShiro();
/**
* 2、执行登录操作
*/
Subject subject = SecurityUtils.getSubject();
System.err.println("Before Login 用户登录状体 >>> "+ subject.isAuthenticated());
String username = "zhangsan";
String password = "123";
ShiroUtils.login(username, password);
System.err.println("After Login 用户登录状体 >>> "+ subject.isAuthenticated());
System.err.println("是否拥有[admin]角色 >> "+ subject.hasRole("admin"));
boolean[] rolesBoolList = subject.hasRoles(Arrays.asList("admin", "guest"));
System.err.println("是否拥有[admin、guest]角色 >> "+ Arrays.toString(rolesBoolList));
System.err.println("是否拥有[product:view]权限 >> "+ subject.isPermitted("product:view"));
boolean[] permittedBoolList = subject.isPermitted("product:view", "product:edit", "product:create", "product:remove");
System.err.println("是否拥有[product的view、edit、create、remove]的权限 >> "+ Arrays.toString(permittedBoolList));
/**
* 3、执行登出操作
*/
ShiroUtils.logout();
}
}
输出如下:
Before Login 用户登录状体 >>> false
-- 执行认证逻辑 --
username >>> zhangsan
password >>> 123
realName >>> javaboy.greamrod.shiro.ShiroRealm_0
principal >>> zhangsan
credentials >>> [C@6073f712
After Login 用户登录状体 >>> true
-- 执行授权逻辑 --
principals >>> zhangsan
principal >>> zhangsan
是否拥有[admin]角色 >> true
-- 执行授权逻辑 --
principals >>> zhangsan
principal >>> zhangsan
-- 执行授权逻辑 --
principals >>> zhangsan
principal >>> zhangsan
是否拥有[admin、guest]角色 >> [true, true]
-- 执行授权逻辑 --
principals >>> zhangsan
principal >>> zhangsan
是否拥有[product:view]权限 >> true
-- 执行授权逻辑 --
principals >>> zhangsan
principal >>> zhangsan
-- 执行授权逻辑 --
principals >>> zhangsan
principal >>> zhangsan
-- 执行授权逻辑 --
principals >>> zhangsan
principal >>> zhangsan
-- 执行授权逻辑 --
principals >>> zhangsan
principal >>> zhangsan
是否拥有[product的view、edit、create、remove]的权限 >> [true, true, true, true]
shiro
框架中什么时候调用自定义Realm
类中的认证方法、权限方法
- 什么时候调用认证方法:
- 行
SecurityUtils.getSubject().login()
方法,就会调用自定义Realm
类中的doGetAuthenticationInfo()
认证方法。
-
什么时候调用授权方法:
是否拥有角色:
-
执行
SecurityUtils.getSubject().hasRole("admin")
方法,就会执行一次自定义Realm类中的doGetAuthorizationInfo()
授权方法。 -
执行
SecurityUtils.getSubject().hasRoles(Arrays.asList("admin", "guest")
方法,就会执行两次自定义Reaml类中的doGetAuthorizationInfo()
方法。是否拥有权限:
-
执行
SecurityUtils.getSubject().isPermitted("product:view")
方法,就会执行一次自定义Realm类中的doGetAuthorizationInfo()
授权方法。 -
执行
SecurityUtils.getSubject().isPermitted("product:view", "product:edit", "product:create", "product:remove")
方法,就会执行四次自定义Reaml类中的doGetAuthorizationInfo()
方法。
Shrio
框架中的提供异常信息
ShiroException
|---UnknownAccountException
|---CredentialsException
|---DisabledAccountException
|---LockedAccountException
UnknownAccountException
异常
//抛出UnknownAccountException异常:
if (user == null) {
throw new UnknownAccountException("账户不存在异常!!!");
}
=========================================================================================
//异常信息:
Exception in thread "main" org.apache.shiro.authc.UnknownAccountException: 账户不存在异常!!!
at javaboy.greamrod.shiro.ShiroRealm.doGetAuthenticationInfo(ShiroRealm.java:63)
at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:571)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:273)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:275)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260)
at javaboy.greamrod.shiro.ShiroUtils.login(ShiroUtils.java:30)
at javaboy.greamrod.MainApp.main(MainApp.java:23)
CredentialsException
异常
//抛出CredentialsException异常:
if (! user.getPassword().equals(password)) {
throw new CredentialsException("密码不存在异常!!!");
}
=========================================================================================
//异常信息:
Exception in thread "main" org.apache.shiro.authc.CredentialsException: 密码不存在异常!!!
at javaboy.greamrod.shiro.ShiroRealm.doGetAuthenticationInfo(ShiroRealm.java:65)
at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:571)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:273)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:275)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260)
at javaboy.greamrod.shiro.ShiroUtils.login(ShiroUtils.java:30)
at javaboy.greamrod.MainApp.main(MainApp.java:23)
DisabledAccountException
异常
//抛出DisabledAccountException异常:
if (user.getStatus() == 1) {
throw new DisabledAccountException("用户被禁用异常!!!");
}
=========================================================================================
//异常信息:
Exception in thread "main" org.apache.shiro.authc.DisabledAccountException: 用户被禁用异常!!!
at javaboy.greamrod.shiro.ShiroRealm.doGetAuthenticationInfo(ShiroRealm.java:67)
at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:571)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:273)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:275)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260)
at javaboy.greamrod.shiro.ShiroUtils.login(ShiroUtils.java:30)
at javaboy.greamrod.MainApp.main(MainApp.java:23)
LockedAccountException
异常
//抛出LockedAccountException异常:
if(user.getStatus() == 2) {
throw new LockedAccountException("用户被锁定异常!!!");
}
=========================================================================================
//异常信息:
Exception in thread "main" org.apache.shiro.authc.LockedAccountException: 用户被锁定异常!!!
at javaboy.greamrod.shiro.ShiroRealm.doGetAuthenticationInfo(ShiroRealm.java:69)
at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:571)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:273)
at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:275)
at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260)
at javaboy.greamrod.shiro.ShiroUtils.login(ShiroUtils.java:30)
at javaboy.greamrod.MainApp.main(MainApp.java:23)