Shiro添加自己的Filter

因为前后端分离,添加了自己的过滤器,根据cookie判断传过来的uuid是否是登录的token

使用到了cache,稍后会加上源码也稍后上传

ShiroConfiguration
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
    //这里设置了自己的过滤器
    ShiroFilterFactoryBean shiroFilter = new CustomShiroFilterFactoryBean();
    shiroFilter.setSecurityManager(securityManager);
    shiroFilter.setLoginUrl("/auth.html");
    shiroFilter.setUnauthorizedUrl("/403.html");

    Map<String, String> filterMap = new LinkedHashMap<>();
    //开放swagger资源 start
    filterMap.put("/v2/api-docs", "anon");
    filterMap.put("/webjars/**", "anon");
    filterMap.put("/swagger-resources/**", "anon");
    filterMap.put("/swagger-ui.html", "anon");
    //开放swagger资源 end
    filterMap.put("/api/**", "anon");
    filterMap.put("/assets/**", "anon");
    filterMap.put("/fonts/**", "anon");
    filterMap.put("/maps/**", "anon");
    filterMap.put("/api/_devops_/init", "anon");
    filterMap.put("/configuration/ui", "anon");
    filterMap.put("/configuration/security", "anon");
    filterMap.put("/scripts/**", "anon");
    filterMap.put("/styles/**", "anon");
    filterMap.put("/auth.html", "anon");
    filterMap.put("/index.html", "anon");
    filterMap.put("/**", "authc");
    shiroFilter.setFilterChainDefinitionMap(filterMap);

    return shiroFilter;
}


CustomShiroFilterFactoryBean

public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean {
    public static final String UUID_HEADER = "uuid";
    private static final Pattern resourceSuffix = Pattern.compile("\\.\\w{1,15}$");

    @Autowired
    private CacheService cacheService;

    @Override
    protected AbstractShiroFilter createInstance() throws Exception {
        // TODO Auto-generated method stub

        FilterChainManager manager = createFilterChainManager();

        // Expose the constructed FilterChainManager by first wrapping
        // it in a
        // FilterChainResolver implementation. The AbstractShiroFilter
        // implementations
        // do not know about FilterChainManagers - only resolvers:
        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
        chainResolver.setFilterChainManager(manager);

        AbstractShiroFilter filter = new AbstractShiroFilter() {

            protected boolean pathMatches(String pattern, String path) {
                PatternMatcher pathMatcher = chainResolver.getPathMatcher();
                return pathMatcher.matches(pattern, path);
            }

            protected boolean isRequestIgnored(ServletRequest request, ServletResponse response) {
                if (!manager.hasChains()) {
                    return false;
                }

                String requestURI = WebUtils.getPathWithinApplication(WebUtils.toHttp(request));
                SimpleNamedFilterList configuredFilter = null;
                Object anonFilter = null;

                for (String pathPattern : manager.getChainNames()) {

                    // If the path does match, then pass on to the subclass implementation for specific checks:
                    if (pathMatches(pathPattern, requestURI)) {
                        configuredFilter = (SimpleNamedFilterList) manager.getChain(pathPattern);
                        break;
                    }
                }

                if(configuredFilter != null && !configuredFilter.isEmpty()){
                    anonFilter = configuredFilter.get(0);
                }

                if(anonFilter != null && anonFilter instanceof AnonymousFilter){
                    return true;
                }else{
                    HttpServletRequest hsr = (HttpServletRequest) request;
                    // bypass resource
                    if ("GET".equalsIgnoreCase(hsr.getMethod()) && (resourceSuffix.matcher(hsr.getRequestURI()).find() || "/".equals(hsr.getRequestURI()))){
                        return true;
                    }

                    return false;
                }
            }

            @Override
            protected WebSubject createSubject(ServletRequest request, ServletResponse response) {
                WebSubject ws = super.createSubject(request, response);
                if(isRequestIgnored(request,response)){
                    return ws;
                }

                if(request instanceof HttpServletRequest == false){
                    throw new RuntimeException("Inner error. The request is not a HttpServletRequest");
                }

                HttpServletRequest hsr = (HttpServletRequest)request;
                String uuid = hsr.getHeader(UUID_HEADER);
                if (uuid != null && !uuid.isEmpty()) {
                    String cache = cacheService.getValue(uuid);
                    if(cache == null || cache == ""){
                        throw new AuthenticationException("uuid is illegal.");
                    }
                    String cache_uuid = cache.split("_")[0];
                    String userId = cache.split("_")[1];
                    String username = cache.split("_")[2];
                    String password = cache.split("_")[3];
                    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
                    if(!cache_uuid.equals(uuid)){
                        throw new AuthenticationException("uuid is illegal.");
                    }
                    try {
                        ws.login(token);
                    } catch (AuthenticationException e) {
                        throw new RuntimeException("Inner error. Failed to login with shiro.");
                    }
                } else {
                    throw new ExceptionResponse("no "+UUID_HEADER+" header assigned");
                }
                return ws;
            }
        };
        filter.setSecurityManager((WebSecurityManager) getSecurityManager());
        filter.setFilterChainResolver(chainResolver);
        return filter;
    }
}
 
LoginController

@RequestMapping(value = "/login",method = RequestMethod.POST)
    @ApiOperation(value = "用户登录",notes = "根据用户名密码判断用户")
    @ApiImplicitParam(value = "Map",required = true,dataType = "Map")
    public Map<String,Object> login(@RequestBody Map<String, String> map) {
        Map<String , Object> resurt = new HashMap<>();
        UsernamePasswordToken token = null;
        try {
            String username = map.get("username");
            //sha256加密
            String password = new Sha256Hash(map.get("password")).toHex();
            User user = userService.findByUserName(username);
//      账号不存在
        if(user == null) {
            throw new ExceptionResponse("用户名不正确");
        }
        //密码错误
        if(!password.equals(user.getPassword())) {
            throw new ExceptionResponse("密码不正确");
        }
        //账号禁用
        if("0".equals(user.getStatus())){
            throw new ExceptionResponse("用户已被禁用,请联系管理员");
        }
            Subject subject = ShiroUtils.getSubject();
            token = new UsernamePasswordToken(username, password);
            String uuid = UUIDGenerator.creatUUID();
            resurt.put("uuid",uuid);
            cacheService.setValue(uuid,uuid + "_" + user.getId() + "_" + user.getUsername() + "_" + user.getPassword());
            subject.login(token);
        }catch (Exception e){
            System.out.println(e);
        }
        return resurt;
    }

测试:

1.没登陆:


2.登录 : 


将返回的uuid设置到header中


整合shiro可以参考:http://blog.csdn.net/a295277302/article/details/77454119

ShiroFilterFactoryBean源码及拦截原理深入分析:http://blog.csdn.net/u012345283/article/details/44199791


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
web.xml配置 因为我们是与spring进行集成的,而spring的基本就是web项目的xml文件。所以我们在web.xml中配置shiros的过滤拦截。正常情况下,我们需要将shirofilter配置在所有的filter前面,当然和encodingFilter这个filter是不区分前后的。因为两者互相不影响的。spring-shiro.xml 这里我们将来看看spring-shiro.xml的配置,这里我采取倒叙的方式讲解,我觉的倒叙更加的有助于我们理解代码。首先我们还记得在web.xml中配置的那个filter吧,名字shiroFilter,对spring-shiro.xml配置文件就是通过这个filter展开的。首先我们在web.xml配置的过滤器实际上是配置ShiroFilterFactoryBean,所以在这里需要将ShiroFilterFactoryBean定义为shiroFilter <!-- Shiro的核心安全接口,这个属性是必须的 --> <!-- 要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.html"页面 --> <!-- 登录成功后要跳转的连接 --> <!-- 用户访问未对其授权的资源时,所显示的连接 --> <!-- 若想更明显的测试此属性可以修改它的值,如unauthor.jsp,然后用[玄玉]登录后访问/admin/listUser.jsp就看见浏览器会显示unauthor.jsp --> <!-- Shiro连接约束配置,即过滤链的定义 --> <!-- 此处可配合我的这篇文章来理解各个过滤连的作用http://blog.csdn.net/jadyer/article/details/12172839 --> <!-- 下面value值的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的 --> <!-- anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种 --> <!-- authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter --> /statics/**=anon /login.html=anon /sys/schedule.html=perms[sys:schedule:save] /sys/login=anon /captcha.jpg=anon /**=authc
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值