Shiro最佳实践(四)基于ini配置文件的自定义认证

Apache Shiro
placeholder image
admin 发布于:2019-08-03 22:56:23
阅读:loading

本文所谓的基于ini配置文件的自定义认证是从ini文件中定义用户账户及角色权限信息,通过自己实现Realm的方式进行登录授权,比较简单,参考具体如下:

配置文件

#按用户名与密码登录
[users]
chendd=www.chendd.cn,admin,manager

[roles]
admin=*
manager="user:insert,update,delete","concat:*"

自定义授权

package cn.chendd.shiro.custom;

import ...;

/**
 * @author chendd
 *
自定义登录认证实现
 
*/
public class LoginRealm extends IniRealm {

    Logger
logger = LoggerFactory.getLogger(this.getClass());

   
public LoginRealm(String resourcePath) {
       
super(resourcePath);
    }

   
/**
     *
自定义认证器名称
    
*/
   
@Override
   
public String getName() {
       
return "chendd-login-realem";
    }

   
@Override
   
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
       
logger.debug("待认证的用户名为:{},密码为:{}" ,
                userToken.getUsername() , userToken.getPassword());
        SimpleAccount account =
this.getUser(userToken.getUsername());
       
if(account == null){
           
throw new UnknownAccountException("用户不存在!");
        }
       
if(! account.getCredentials().toString().equals(new String(userToken.getPassword()))){
           
throw new AuthenticationException("用户名或密码不匹配!");
        }
        Object credentials = account.getCredentials();
        Object principal = token.getPrincipal();
       
//将用户account对象存储至用户账号主体中
       
SimpleAuthenticationInfo authInfo = new SimpleAuthenticationInfo(account , credentials , this.getName());
       
return authInfo;
    }

   
@Override
   
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
       
//获取主体用户账号信息,将账号中的角色、权限信息进行授权
       
SimpleAccount account = (SimpleAccount) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo simpleAuthor =
new SimpleAuthorizationInfo();
        System.
out.println(simpleAuthor.getRoles());
        simpleAuthor.setRoles((Set<String>) account.getRoles());
        simpleAuthor.setObjectPermissions((Set<Permission>) account.getObjectPermissions());
       
return simpleAuthor;
    }
}

测试代码

package cn.chendd.shiro.examples.login;

import ...;

/**
 * @author chendd
 *
自定义登录验证器(模拟从数据库中获取账号登录)
 
*/
public class LoginRealmTest extends LoginTest {

   
@Test
   
public void testLoginRealm() {
       
logger.info("###测试自定义认证器登录--用户名 {} ,密码 {} ###" , username , password);
        String resourcePath =
"classpath:shiro/shiro-loginRealm.ini";
        Realm realm =
new LoginRealm(resourcePath);
        SecurityManager securityManager =
new DefaultSecurityManager(realm);
        SecurityUtils.setSecurityManager(securityManager);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token =
new UsernamePasswordToken(username, password);
       
try {
            Subject loginSubject = securityManager.login(subject, token);
           
if (loginSubject.isAuthenticated()) {
                
logger.debug("用户已经认证");
            }
           
logger.info("用户名 {} 认证成功", loginSubject.getPrincipal());
           
logger.info("是否拥有角色manager{}", loginSubject.hasRole("manager"));
           
logger.info("是否拥有联系人查询权限:{}", loginSubject.isPermitted("concat:select"));

        }
catch (AuthenticationException e) {
           
logger.error("用户名 {} 认证失败", username, e);
        }
    }

}

运行结果

image.png

另外的一个自定义认证

package cn.chendd.shiro.custom;

import ...

/**
 *
自定义用户、角色、权限认证器
 
* @author chendd
 */
public class PrimisionRealm extends IniRealm {

    Logger
logger = LoggerFactory.getLogger(this.getClass());

   
@Override
   
public String getName() {
       
return "chendd-primision-realm";
    }

   
//授权
   
@Override
   
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo author =
new SimpleAuthorizationInfo();
        String userName = (String) principals.getPrimaryPrincipal();
       
logger.debug("###构造用户[{}]的角色权限授权信息###" , userName);
        Set<String> roles =
new HashSet<>();//角色集合
       
Set<String> primisions = new HashSet<>();//权限集合
       
if("admin".equals(userName)){
            roles.add(
"admin");//管理员角色,任意权限
           
primisions.add("*");
        }
else if("chendd".equals(userName)){
            roles.add(
"coder");//coder角色及权限
           
primisions.add("usermanager:*");
            primisions.add(
"logmanager:select");
            primisions.add(
"menumanager:insert");
            primisions.add(
"menumanager:delete");
            roles.add(
"tester");//tester角色及权限
           
primisions.add("menumanager:test:test");
            primisions.add(
"menumanager:insert");
        }
else if("tt".equals(userName)){
            roles.add(
"tester");//tester角色及权限
           
primisions.add("menumanager:test:test");
            primisions.add(
"menumanager:insert");
        }
else {
           
throw new AuthenticationException("用户名与密码不匹配!");
        }
        author.addRoles(roles);
        author.addStringPermissions(primisions);
       
return author;
    }

   
//认证
   
@Override
   
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        UsernamePasswordToken userToken = (UsernamePasswordToken) token;
        String userName = userToken.getUsername();
        String password =
new String(userToken.getPassword());
       
boolean flag = false;
       
if("admin".equals(userName) && "admin123".equals(password)){
            flag =
true;
        }
else if("chendd".equals(userName) && "chendd123".equals(password)){
            flag =
true;
        }
else if("tt".equals(userName) && "tt123".equals(password)){
            flag =
true;
        }
else {
           
throw new AuthenticationException("用户名与密码不匹配!");
        }
        AuthenticationInfo authent =
new SimpleAuthenticationInfo(token.getPrincipal() , token.getCredentials() , this.getName());
       
return authent;
    }
}

 点赞


 发表评论

当前回复:作者

 评论列表


留言区