Shiro学习

1.自定义ShiroConfiguration

package com.hgys.iptv.configuration.shiro;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
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 org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author: wangzhen
 * @date:2019/4/19 16:53
 */
@Configuration
public class ShiroConfiguration {

    //将自己的验证方式加入容器
    @Bean
    public ShiroRealmDetails getShiroRealmDetails() {
        return new ShiroRealmDetails();
    }

    //权限管理,配置主要是Realm的管理认证
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(getShiroRealmDetails());
        securityManager.setSessionManager(getShiroSessionManager());
        return securityManager;
    }

    //自定义session管理
    @Bean
    public ShiroSessionManager getShiroSessionManager(){
        return new ShiroSessionManager();
    }
    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
//        System.out.println("ShiroConfiguration.shiroFilterFactoryBean()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //注意过滤器配置顺序 不能颠倒
        filterChainDefinitionMap.put("/logout", "logout");
        // 配置不会被拦截的action 顺序判断
//        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/LoginFail", "anon");
        filterChainDefinitionMap.put("/unauth", "anon");
        // 现在资源的角色
       // filterChainDefinitionMap.put("/admin.html", "roles[admin]");
        // filterChainDefinitionMap.put("/user.html", "roles[user]");
        filterChainDefinitionMap.put("/**", "authc");
        //filterChainDefinitionMap.put("/**", "user");--设置rememberMe(true),在/**=authc权限下是不起作用的,需要user

        //配置shiro默认登录action,前后端分离中登录界面跳转应由前端路由控制,后台仅返回json数据
        shiroFilterFactoryBean.setLoginUrl("/loginHtml");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/LoginSuccess");
        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    //处理未授权异常跳转问题
    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver(){
        SimpleMappingExceptionResolver resolver=new SimpleMappingExceptionResolver();
        Properties properties = new Properties();
        properties.setProperty("UnauthorizedException","/unauth");
        resolver.setExceptionMappings(properties);
        return resolver;
    }
}

2.继承AuthorizingRealm重写两个方法

package com.hgys.iptv.configuration.shiro;

import com.hgys.iptv.model.Permission;
import com.hgys.iptv.model.Role;
import com.hgys.iptv.model.User;
import com.hgys.iptv.service.LoginService;
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.springframework.beans.factory.annotation.Autowired;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * @author: wangzhen
 * @date:2019/4/19 16:39
 */
public class ShiroRealmDetails extends AuthorizingRealm {

    @Autowired
    private LoginService loginService;

    /**
     * 鉴权授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("进入doGetAuthorizationInfo授权。");
        //获取登录用户名
        String principal= (String) principalCollection.getPrimaryPrincipal();
        // 根据用户名来查询数据库赋予用户角色,权限(查数据库)
        User user = loginService.findByUsername(principal);
        SimpleAuthorizationInfo simpleAuthorizationInfo = null;
        if(user!=null){
            Set<String> roles = new HashSet<>();
            Set<String> permissions = new HashSet<>();
            simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            for (Role role:user.getRoles()) {
                roles.add(role.getName());
                for (Permission permission:role.getPermissions()) {
                    permissions.add(permission.getPermission());
                }
            }
            //关联角色
            simpleAuthorizationInfo.setRoles(roles);
            //关联权限
            simpleAuthorizationInfo.setStringPermissions(permissions);
        }

        System.out.println(principal+"具有的角色:=="+Arrays.toString(simpleAuthorizationInfo.getRoles().toArray()));
        System.out.println(principal+"具有的权限:=="+Arrays.toString(simpleAuthorizationInfo.getStringPermissions().toArray()));
        return simpleAuthorizationInfo;
    }


    /**
     * 获取身份验证信息
     * @param authenticationToken 用户身份信息 token
     * @return 返回封装了用户信息的 AuthenticationInfo 实例
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("进入doGetAuthenticationInfo查用户信息。");
        if (authenticationToken.getPrincipal() == null) {
            return null;
        }
//        UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
//        // 获得从表单传过来的用户名
//        String username = upToken.getUsername();
        //获取用户信息
        String name = authenticationToken.getPrincipal().toString();
        // 从数据库查看是否存在用户
        User user = loginService.findByUsername(name);
        if (user == null) {
            throw new UnknownAccountException("用户名不存在!");
        }
        //验证authenticationToken和simpleAuthenticationInfo的信息
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                name,
                user.getPassword(),
                getName());
        return simpleAuthenticationInfo;
    }
}

3.自定义ShiroSessionManager(可选)

package com.hgys.iptv.configuration.shiro;

import org.springframework.util.StringUtils;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;

/**
 * @author: wangzhen
 * @date:2019/4/20 21:13
 */
public class ShiroSessionManager extends DefaultWebSessionManager {
    private static final String AUTHORIZATION = "Authorization";

    private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";

    @Override
    protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
        String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
        //如果请求头中有 Authorization 则其值为sessionId
        if (!StringUtils.isEmpty(id)) {
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
            return id;
        } else {
            //否则按默认规则从cookie取sessionId
            return super.getSessionId(request, response);
        }
    }
}

4.自定义ShiroCatheManager(可选)

5.subject.login(new UsernamePasswordToken(username, password))

    @RequestMapping("/login")
    public String login(@RequestParam("username") String username, @RequestParam("password") String password) {
        Subject subject = SecurityUtils.getSubject();
        // 验证用户是否已登录过
        if (!subject.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
           // token.setRememberMe(true);
            try {
                subject.login(token);
                boolean f =subject.hasRole("ROLE_ADMIN");
                System.out.println("admin角色标志=="+f);
                return "redirect:/LoginSuccess";
            } catch (IncorrectCredentialsException e) {
                System.out.println("登录密码错误!!!" + e);
                return "redirect:/LoginFail";
            } catch (ExcessiveAttemptsException e) {
                System.out.println("登录失败次数过多!!!" + e);
            } catch (LockedAccountException e) {
                System.out.println("帐号已被锁定!!!" + e);
            } catch (DisabledAccountException e) {
                System.out.println("帐号已被禁用!!!" + e);
            } catch (ExpiredCredentialsException e) {
                System.out.println("帐号已过期!!!" + e);
            } catch (UnknownAccountException e) {
                System.out.println("帐号不存在!!!" + e);
            } catch (UnauthorizedException e) {
                System.out.println("您没有得到相应的授权!" + e);
                return "redirect:/unauth";
            } catch (Exception e) {
                System.out.println("出错!!!" + e);
            }
            return "/login";
        }
        // 已成功登录过则直接重定向到LoginSuccess
        return "redirect:/LoginSuccess";
    }

6.在方法上设置需要权限

    @RequestMapping("/showUserHtml")
    @RequiresRoles(value = { "ROLE_USER", "ROLE_ADMIN"},logical = Logical.OR)
   // @RequiresPermissions("user:query")
    @RequiresPermissions("QUERY")
    public String userHtml() {
        return "/user";
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值