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

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

作者:互联网

<style></style>

一.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 有顺序的

标签:md,权限,cm,color,留言,CodeMirror,0px,margin,shiro
来源: https://www.cnblogs.com/angiechiu/p/13229786.html