Java的权限框架Shiro

shiro中的概念:

Subject:代表当前登录或者访问的用户

Principals:一般指用户名等,唯一表明subject身份也就是当前用户身份的东西

Credentials:凭证,一般指密码,对当前登录用户进行验证

Realms:域,一般是指存储用户信息(用户名,密码,权限,角色)的数据库,也就是保存用户权限等信息的数据源

SecurityManager:shiro安全管理的顶级对象。它集合或者说调用所有其他相关组件,负责所有安全和权限相关处理过程,就像中央集权的政府。

shiro的子系统:

Shiro的主要功能:认证,授权,加密,session管理等,每一个主要功能对应于shiro的一个子系统

①Authentication认证子系统:处理用户登录,验证用户登录。

如:登录认证时调用subject.login(AuthenticationToken   token)方法,AuthenticationToken是一个接口。会分别调用实现类的getPrincipal()和getCredentials()来获得用户名和密码。

Subject代表当前用户

通常做法:new一个UsernamePasswordToken的对象:

UsernamePasswordToken token = new UsernamePasswordToken(“username”,”password”);

然后subject.login(token);就去登录。

代码实例:

    @RequestMapping(value="/loginController", method=RequestMethod.POST)

    public String login(String userName, String password, String rememberMe, String type, HttpServletRequest req) {

        String error = null;

        Subject subject = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken(userName, password);

        if(rememberMe != null && "true".equals(rememberMe))

            token.setRememberMe(true);    // 记住我        

        try {

            subject.login(token);

        } catch (UnknownAccountException | IncorrectCredentialsException e1) {

            error = "用户名或密码错误";

        }catch(ExcessiveAttemptsException e){

            userService.lockAccountByNo(no);     // 锁定账户

            error = "超过了尝试登录的次数,您的账户已经被锁定。";

        }catch (AuthenticationException e) {    // 其他错误

            if(e.getMessage() != null)

                error = "发生错误:" + e.getMessage();

            else

                error = "发生错误,无法登录。";

        }

authentication子系统会将password进行加密,然后使用username和加密后的password和从数据库中根据username获的密码进行比较,相同就登录成功,不相同就登录失败,或者用户名不正确也会登录失败。

②authorization授权子系统(访问控制)

认证子系统会获得用户所拥有的权限,在需要判断用户是否有某权限或者是角色时,会自动回调方法doGetAuthorizationInfo来获得用户的角色和权限,我们只需要在数据库中获得相关信息。

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        String no = (String)principals.getPrimaryPrincipal();

        User user = userService.getUserByNo(no);

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        authorizationInfo.setRoles(userService.findRolesByUserId(user.getId()));

     authorizationInfo.setStringPermissions(userService.findPermissionsByUserId(user.getId()));

        return authorizationInfo;

    }    

public class SimpleAuthorizationInfo implements AuthorizationInfo {

    protected Set<String> roles;

    protected Set<String> stringPermissions;

    protected Set<Permission> objectPermissions;

    public SimpleAuthorizationInfo() {

}

(1)使用字符串来表示你拥有某个角色或者拥有某个权限的

(2)两种访问控制方式:基于角色的访问控制,基于资源的访问控制

(3)访问控制:是指对于某个资源,当前用户是否有访问的权限。

(4)权限的字符串表示方式:

“资源:操作:对象实例ID”表示:对哪个资源的哪个实例可以进行哪些操作,支持通配符。

如:”user:delete:1”就表示对user表的id等于1对应的数据或者对象,可以进行删除操作。

“user:update,delete”表示对user表(的任意实例)进行更新和删除操作,等价于”user:update,delete:*”

所以shiro的访问控制可以控制到具体实例,或者说具体那条数据库记录,也可以在表级别控制。如果省略对象实例ID部分,就是在表级别控制。

(5)权限相关表的设计

A:简单情况,使用“基于角色的访问控制”,不涉及到权限,仅仅通过判断是否有某角色来判断访问控制,那么只需要增加一个角色表(roles)和一个角色_用户的多对多的中间表:user_roles

B:如果仅仅使用权限来控制访问,那么就可以仅仅增加一个权限表(priv)和一个权限_用户的中间表(user_priv)

C:如果既要用到角色,又要用到权限(权限根据角色推荐出来),那么就要增加:角色表,用户角色表,权限表,角色权限表。

③Cryptography加密子系统:

该子系统分为两部分:基于hash的单向加密算法,基于经典加密解密算法。

一般而言,对于登陆用户的密码的加密都是采用单向的hash加密算法,因为如果密码可以被解密的话,用户的密码会被破解。单向加密算法是无法被解密的。

1) 单向加密算法:一般使用sha系列算法,MD2/MD5安全性不足。

Sha256Hash算法:

public class Sha256Hash extends SimpleHash {

    public static final String ALGORITHM_NAME = "SHA-256";

    public Sha256Hash() {

        super(ALGORITHM_NAME);

    }

    public Sha256Hash(Object source) {

        super(ALGORITHM_NAME, source);

    }

    public Sha256Hash(Object source, Object salt) {

        super(ALGORITHM_NAME, source, salt);

    }

    public Sha256Hash(Object source, Object salt, int hashIterations) {

        super(ALGORITHM_NAME, source, salt, hashIterations);

    }

    public static Sha256Hash fromHexString(String hex) {

        Sha256Hash hash = new Sha256Hash();

        hash.setBytes(Hex.decode(hex));

        return hash;

    }

    public static Sha256Hash fromBase64String(String base64) {

        Sha256Hash hash = new Sha256Hash();

        hash.setBytes(Base64.decode(base64));

        return hash;

    }

}

实现密码锁实例:

String sha256 = new Sha256Hash("admin", "11d23ccf28fc1e8cbab8fea97f101fc1d", 2).toString();

2) 双向经典加密解密算法
主要提供两种加密解密算法:AES、Blowfish

AES:

  AesCipherService aesCipherService = new AesCipherService();

        aesCipherService.setKeySize(128); // 设置key长度

        // 生成key

        Key key = aesCipherService.generateNewKey();

        // 加密

        String encrptText = aesCipherService.encrypt(text.getBytes(), key.getEncoded()).toHex();

        // 解密

        String text2 = new String(aesCipherService.decrypt(Hex.decode(encrptText), key.getEncoded()).getBytes());

        System.out.println(text2.equals(text));

Key 表示 秘钥,就相当于 Hash 算法中的 salt,秘钥不同,最终的密文也就不同。不同的是解密时是需要使用加密时相同的秘钥才能解密成功。

Blowfish:

 BlowfishCipherService blowfishService = new BlowfishCipherService();

        blowfishService.setKeySize(128);

        Key bKey = blowfishService.generateNewKey();

        String encrpt = blowfishService.encrypt("admin".getBytes(), bKey.getEncoded()).toHex();

        String dec = new String(blowfishService.decrypt(Hex.decode(encrpt), bKey.getEncoded()).getBytes());

        System.out.println("admin".equals(dec));

使用 DefaultBlockCipherService 实现加密解密:

 //使用Java的JCA(javax.crypto.Cipher)加密API,常见的如 AES, Blowfish

        DefaultBlockCipherService cipherService = new DefaultBlockCipherService("AES");

        cipherService.setKeySize(128);

        //生成key

        bKey = cipherService.generateNewKey();

        text = "admin";

        //加密

        encrptText = cipherService.encrypt(text.getBytes(), key.getEncoded()).toHex();

        //解密

        text2 = new String(cipherService.decrypt(Hex.decode(encrptText), key.getEncoded()).getBytes());

        System.out.println(text.equals(text2));

DefaultBlockCipherService(BlockCipher)是分组加密的意思,分组是指加密的过程是先进行分组,然后加密。AES 和 Blowfish都是分组加密算法。

④Session management会话管理子系统:

Shiro中session的最大的不同时,他可以使用在非web环境中,对于javaSE的环境也可以使用session的功能,因为他实现了一套不依赖web容器的session机制。

转载于:https://my.oschina.net/u/3727427/blog/1800971

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值