首页 > 其他 > 详细

shiro权限验证(个人看视频记录的,自己使用,大家参考有不懂可留言)

时间:2020-07-03 13:39:50      阅读:52      评论:0      收藏:0      [点我收藏+]

一.shiro权限验证(个人看视频记录的,自己使用,大家参考有不懂可留言)

技术分享图片

I.搭建环境

i.导入坐标
 
 
 
xxxxxxxxxx
 
 
 
 
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.5.3</version>
    </dependency>
</dependencies>
 
ii.配置类

ShiroConfig

 
 
 
xxxxxxxxxx
 
 
 
 
package com.it.fuxinyu.shiro;
?
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
?
import java.util.LinkedHashMap;
import java.util.Map;
?
import static com.it.fuxinyu.config.EncryptionMethodAttributes.ENCRYPTION_TIMES;
import static com.it.fuxinyu.config.EncryptionMethodAttributes.MD5;
import static com.it.fuxinyu.config.ShiroPermissionAttributes.*;
?
@Configuration
public class ShiroConfig {
?
    /**
     * 创建ShiroFilterFactoryBean
     *
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean() {
        /*
           创建ShiroFilterFactoryBean对 Shiro的过滤器
         */
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager());
?
        //配置Shiro的过滤器
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/login/login", ANON);
        filterMap.put("/image/**", ANON);
        filterMap.put("/user/toList", PERMS + "[user:list]");
        filterMap.put("/auth/logout", LOGOUt);
        filterMap.put("/**", AUTHC);
?
?
        /**
         * 弄登录页
         */
        shiroFilterFactoryBean.setLoginUrl("/login/toLogin");
        /**
         * 未授权页面
         */
        shiroFilterFactoryBean.setUnauthorizedUrl("/user/unauthorized");
?
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
?
        return shiroFilterFactoryBean;
    }
?
    /**
     * 创建DefaultWebSecurityManager 用来管理用户主体的Subject
     *
     * @return
     */
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager() {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(getUserRealm());
        return defaultWebSecurityManager;
    }
?
    //shiro的加密使用的是哈希算法+盐加密 我们只需要给他盐和加盐的次数设定加密方式即可
?
    /**
     * 实例化自定义的Realm对象
     *
     * @return
     */
    @Bean
    public UserRealm getUserRealm() {
        UserRealm userRealm = new UserRealm();
        userRealm.setCredentialsMatcher(getCredentialsMatcher());
        return userRealm;
    }
?
    /**
     * 加密方法
     *
     * @return
     */
    @Bean
    public CredentialsMatcher getCredentialsMatcher() {
        //创建HashedCredentialsMatcher对象
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //指定加密方式,可以自定义哈希算法
        hashedCredentialsMatcher.setHashAlgorithmName(MD5);
        //设置加密次数
        hashedCredentialsMatcher.setHashIterations(ENCRYPTION_TIMES);
        //设置加密编码:true表示加密使用的是HEX编码 false表示使用的是Base64编码
        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
        return hashedCredentialsMatcher;
    }
?
}
?
 

ShiroUtils

 
 
 
xxxxxxxxxx
 
 
 
 
package com.it.fuxinyu.shiro;
?
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
?
public class ShiroUtils {
    /**
     * 随机生成 salt 需要指定 它的字符串的长度
     *
     * @param len 字符串的长度
     * @return salt
     */
    public static String generateSalt(int len) {
        //一个Byte占两个字节
        int byteLen = len >> 1;
        SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator();
        return secureRandom.nextBytes(byteLen).toHex();
    }
?
    /**
     * 获取加密后的密码,使用默认hash迭代的次数 1 次
     *
     * @param hashAlgorithm hash算法名称 MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512、etc。
     * @param password      需要加密的密码
     * @param salt          盐
     * @return 加密后的密码
     */
    public static String encryptPassword(String hashAlgorithm, String password, String salt) {
        return encryptPassword(hashAlgorithm, password, salt, 1);
    }
?
    /**
     * 获取加密后的密码,需要指定 hash迭代的次数
     *
     * @param hashAlgorithm  hash算法名称 MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512、etc。
     * @param password       需要加密的密码
     * @param salt           盐
     * @param hashIterations hash迭代的次数
     * @return 加密后的密码
     */
    public static String encryptPassword(String hashAlgorithm, String password, String salt, int hashIterations) {
        SimpleHash hash = new SimpleHash(hashAlgorithm, password, salt, hashIterations);
        return hash.toString();
    }
}
 

UserRealm

 
 
 
xxxxxxxxxx
 
 
 
 
package com.it.fuxinyu.shiro;
?
import com.it.fuxinyu.pojo.User;
import com.it.fuxinyu.service.UserService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
?
public class UserRealm extends AuthorizingRealm {
?
?
    @Autowired
    private UserService userService;
?
    /**
     * 授权
     * <p>
     * 校验访问路径
     *
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
?
        System.out.println("-------授权----------");
?
        //编写授权逻辑
        //从数据库查询出当前用户所拥有的权限字符串进行授权
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
?
        //添加权限字符串
        authorizationInfo.addStringPermission("user:list");
?
        return authorizationInfo;
?
    }
?
?
    /**
     * 认证
     * <p>
     * 进行登录验证
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("----------认证----------");
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        //调用数据库根据用户名查询出用户
        User user = userService.findByName(usernamePasswordToken.getUsername());
?
        if (ObjectUtils.isEmpty(user) || !usernamePasswordToken.getUsername().equals(user.getUserName())) {
            return null;
        }
?
        /**
         * 第一个参数为,假如密码正确就是说登录成功后用户对象,相当于我们以前登陆成功后用户放入session的意思
         * 第二个参数,数据库查询出来的密码,shiro会自动帮我们校验密码是否正确
         * 第三个参数,假如密码正确也就是说登录成功后用户名
         * shiro的加密方式通过盐加次数进行hash加密
         * 比如说1234明文,把1234和某一个字符串(盐)一起加密
         */
?
        //判断密码
        return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), user.getUserName());
    }
?
}
 
iii.工具接口

EncryptionMethodAttributes

 
 
 
xxxxxxxxxx
 
 
 
 
package com.it.fuxinyu.config;
?
/**
 * 加密方式属性接口
 */
public interface EncryptionMethodAttributes {
    /**
     * 加密方式MD5
     */
    String MD5 = "MD5";
    /**
     * 加密方式MD4
     */
    String MD4 = "MD4";
    /**
     * 加密方式SHA_1
     */
    String SHA_1 = "SHA-1";
    /**
     * 加密方式SHA_2
     */
    String SHA_2 = "SHA-2";
    /**
     * 加密方式SHA_256
     */
    String SHA_256 = "SHA-256";
    /**
     * 加密方式SHA_512
     */
    String SHA_512 = "SHA-512";
    /**
     * 加密方式SHA_384
     */
    String SHA_384 = "SHA-384";
    /**
     * 加密次数
     */
    Integer ENCRYPTION_TIMES = 1;
}
 

ShiroPermissionAttributes

 
 
 
xxxxxxxxxx
 
 
 
 
package com.it.fuxinyu.config;
?
/**
 * shiro权限参数
 */
public interface ShiroPermissionAttributes {
?
    /**
     * 不需要登录就能访问的路径
     */
    String ANON = "anon";
    /**
     * 需要登录才能访问
     */
    String AUTHC = "authc";
    /**
     * 该资源必须得到资源权限才可以访问
     */
    String PERMS = "perms";
    /**
     * Basic HTTP身份验证拦截器
     */
    String AUTHC_BASIC = "authcBasic";
    /**
     * 退出拦截器。退出成功后会 redirect到设置的/URI
     */
    String LOGOUt = "logout";
    /**
     * 不创建会话连接器
     */
    String NO_SESSION_CREATION = "noSessionCreation";
    /**
     * 端口拦截器
     */
    String PORT = "port";
    /**
     * rest风格拦截器
     */
    String REST = "rest";
    /**
     * 角色拦截器
     */
    String ROLES = "roles";
    /**
     * ssl拦截器。通过https协议才能通过
     */
    String SSL = "ssl";
    /**
     * 用户拦截器 登录后(authc),第二次没登陆但是有记住我(rememberMe)都可以访问
     */
    String USER = "user";
?
}
 
iV.案例方法

登录

 
 
 
xxxxxxxxxx
 
 
 
 
@RequestMapping("/login")
public String login(User user, Model model) {
?
    //使用shiro编写登录逻辑
    //1.获取subject
    Subject subject = SecurityUtils.getSubject();
    //2.将参数封装成Token对象
    UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUserName(), user.getPassword());
    //3.执行登录方法
    try {
        subject.login(usernamePasswordToken);
        return "redirect:/index/toIndex";
    } catch (IncorrectCredentialsException e) {//这个异常一抛出代表密码错误
        model.addAttribute("message", "密码错误");
        return "/login";
    } catch (AuthenticationException e) {  //如果用户不存在,抛出账户位置异常
        model.addAttribute("message", "账号不存在");
        return "/login";
    }
?
}
 

回去session中的用户

 
 
 
xxxxxxxxxx
 
 
 
 
@RequestMapping("/toAdd")
public String toAdd() {
    Object principal = SecurityUtils.getSubject().getPrincipal();
    User user = null;
    if (principal instanceof User) {
        user = (User) principal;
    }
    System.out.println(user);
    return "add";
}
 

II.总结

一上来就把shiro的配置都写好 , 然后在进行操作,以免忘记 过滤器的map必须是linkedHashMap 有顺序的

shiro权限验证(个人看视频记录的,自己使用,大家参考有不懂可留言)

原文:https://www.cnblogs.com/angiechiu/p/13229786.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!