ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2020-07-03 13:05:55  阅读:257  来源: 互联网

标签:md 权限 cm color 留言 CodeMirror 0px margin 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有