shiro_day02

shiro
1.shiro的授权控制
* 基于过滤器的授权控制
anon   开放权限,用户不需要登录就可以访问
authc  需要登录认证
perms[user]  需要某个或某些权限才能通过,perms[“user,admin”],当有多个参数时必须每个参数都通过
roles[admin]  某个或某些角色才能通过,roles[“admin,user”],当有多个参数时必须每个参数都通过
* 基于注解的授权控制
@RequiresPermissions(value = {"添加用户","修改用户"})
@RequiresRoles(value = {"系统管理员"})
2.注解授权控制注意:
过滤器的授权控制,用户权限不足时通过shiroFilterFactoryBean.setUnauthorizedUrl("/autherror")设置跳转页面;而基于注解授权控制,如果权限不足则会抛出异常500到浏览器,因此需要自定义异常处理类补获异常
3.shiro三大功能:
	身份认证,用户授权,会话管理
4.使用shiro会话管理功能解决单点登录问题
	在web应用中,使用subject.login(token)身份认证成功后,实际上将用户信息存到了HttpSession中,shiro提供了三个默认的会话管理: 
* DefaultSessionManager:用于JavaSE环境
* ServletContainerSessionManager:用于Web环境,直接使用servlet容器的会话(HttpSession)。
* DefaultWebSessionManager:用于web环境,自定义会话管理;使用自定义会话管理,将用户信息保存在redis中,实现单点登录
5.自定义session管理器实现单点登录原理:
	配置SessionDao和SessionManager,当用户第一次登录时,将用户信息信息存储在redis中,key是随机ID,value是用户身份信息和授权信息,并将随机ID作为令牌返回给用户;当用户再次访问服务器,请求头key:Authorization,value:随机ID,然后根据ID从redis中查询用户信息,完成单点登录
6.Postman清除cookie信息:
	点击Send按钮下方的Cookies

在这里插入图片描述
在这里插入图片描述

shiro测试案例
1.定义登录Controller
@RestController
public class LoginController{
	@GetMapping("/login")
    public String doLogin(String username,String password){
       //对密码加密,参数1:需要加密密码,参数2:对密码加盐(通常使用用户名作为盐),参数3:加密次数
       try{
       assword = new Md5Hash(password,username,2);
       UsernamePasswordToken upToken = new UsernamePasswordToken(username,password);
       Subject subject = SecurityUtils.getSubject();
       subject.login(upToken);
       return "登录成功";
       }catch(AuthenticationException e){
       return e.getMessage();
       }
    }
    
    @RequiresRoles(value = {"系统管理员"})
    @RequiresPermissions(value = {"user-save","user-delete"})
    @GetMapping("/findAnnotation")
    public String doFindAnnotation(){
    	return "注解配置,查询到了页面...";
    }
    
    @GetMapping("/findFilter")
    public String doFindFilter(){
   		return "过滤器配置,查询到了页面...";
    }
    
}

2.自定义安全数据源
@Component
public class CustomerRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Override
    public void setName(String name) {
        super.setName("customerRealm");
    }

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //安全数据与认证的第一个参数对应
        User user = (User) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Set<String> roleSet = new HashSet<>();
        Set<String> permissionSet = new HashSet<>();
        for (Role role : user.getRoles()) {
            roleSet.add(role.getName());
            for (Permission permission : role.getPermissions()) {
                permissionSet.add(permission.getName());
            }
        }
        info.setRoles(roleSet);
        info.setStringPermissions(permissionSet);
        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
        String username = upToken.getUsername();
        String password = new String(upToken.getPassword());
        User user = userService.findByName(username);
        if (user == null || !user.getPassword().equals(password))
            throw new AuthenticationException("账号密码不匹配...");
        //保存认证信息,参数1是安全参数,认证获得的就是第一个参数
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, this.getName());
        return info;
    }
}

3.配置shiro注解配置类
@Configuration
public class ShiroConfiguration {
    //安全管理器
    @Bean
    public SecurityManager securityManager(CustomerRealm customerRealm) {
        return new DefaultWebSecurityManager(customerRealm);
    }

    //过滤器
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/autherror?code=1"); //设置登录页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/autherror?code=2"); //授权失败跳转页面
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/user/hello", "anon");	//hello资源不需要认证
        filterMap.put("/user/**", "authc");		//需要认证
        //filterMap.put("/findFilter", "perms[user-find,user-update]");		//权限
        //filterMap.put("/findFilter", "roles[系统管理员]");		//角色
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

    //配置shiro注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }
}

4.自定义异常处理类
@ControllerAdvice
public class BaseExceptionHandler {

    @ExceptionHandler(value = AuthorizationException.class)
    @ResponseBody
    public String error(HttpServletRequest request, HttpServletResponse response,AuthorizationException e) {
		return "权限不足...";
    }
}

shiro单点登录
1.自定义shiro会话管理器
public class CustomerSessionManager extends DefaultWebSessionManager {
    @Override
    protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
        //从请求头中获取Authorization对应的值
        String id = WebUtils.toHttp(request).getHeader("Authorization");
        if (StringUtils.isEmpty(id)) {
            //如果ID为空,说明用户当前在登录认证,生成一个ID,并存入Authorization中
            return super.getSessionId(request, response);
        }
        //设置sessionId的来源,header
        request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "header");
        //设置sessionId的值,id
        request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
        //设置sessionId有效
        request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
        return id;
    }
}

2.配置shiro注解配置类
@Configuration
public class ShiroConfiguration {

    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    //安全管理器
    @Bean
    public SecurityManager securityManager(CustomerRealm customerRealm
            , SessionManager sessionManager, RedisCacheManager redisCacheManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(customerRealm);
        securityManager.setSessionManager(sessionManager);
        securityManager.setCacheManager(redisCacheManager);
        return securityManager;
    }

    //过滤器
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        shiroFilterFactoryBean.setLoginUrl("/autherror?code=1"); //设置登录页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/autherror?code=2"); //授权失败跳转页面
        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/user/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

    //配置shiro注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }


    //redis管理器
    @Bean
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        return redisManager;
    }

    //redis缓存管理器
    @Bean
    public RedisCacheManager redisCacheManager(RedisManager redisManager) {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager);
        return redisCacheManager;
    }

    //redis存储工具
    @Bean
    public RedisSessionDAO redisSessionDao(RedisManager redisManager) {
        RedisSessionDAO redisSessionDao = new RedisSessionDAO();
        redisSessionDao.setRedisManager(redisManager);
        return redisSessionDao;
    }


    //自定义会话管理器
    @Bean
    public DefaultWebSessionManager sessionManager(RedisSessionDAO redisSessionDao) {
        CustomerSessionManager customerSessionManager = new CustomerSessionManager();
        customerSessionManager.setSessionDAO(redisSessionDao);
        return customerSessionManager;
    }
}
shiro整合spring boot坐标
<!--shiro和spring整合-->
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-spring</artifactId>
	<version>1.3.2</version>
</dependency>
<!--shiro核心包-->
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-core</artifactId>
	<version>1.3.2</version>
</dependency>
<!--shiro与redis整合-->
<dependency>
	<groupId>org.crazycake</groupId>
	<artifactId>shiro-redis</artifactId>
	<version>3.0.0</version>
</dependency>
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、下4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、下4载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值