shiro#springboot
1.
shiro的使用围绕着securityManager,权限需要从realm中来。
securityManager可以设置realm或者realms,或者通过设置authenticator来设置realm或realms。
realm中可以设置密码匹配器,credentialsMatcher,从而实现密码的加解密处理。
登录操作需要使用AuthenticationToken的子类的实例携带用户信息,传递给realm的认证方法,认证方法返回的是AuthenticationInfo实例,如果使用盐值,需要使用SimpleAuthenticationInfo来自动匹配及返回用户认证信息。
授权操作是使用PrincipalCollection的子类的实例,携带身份信息,传递给realm的鉴权方法,鉴权方法返回的是AuthorizationInfo的实例。
ByteSource salt = ByteSource.Util.bytes(user.getSalt());用于得到盐值密码。
2. 在spring boot中使用shiro时候必须要定义过滤器链,有如下两种方式配置:
方式1:
@Bean public ShiroFilterChainDefinition shiroFilterChainDefinition() { DefaultShiroFilterChainDefinition chain = new DefaultShiroFilterChainDefinition(); //哪些请求可以匿名访问 chain.addPathDefinition("/user/login", "anon"); chain.addPathDefinition("/page/401", "anon"); chain.addPathDefinition("/page/403", "anon"); chain.addPathDefinition("/t5/hello", "anon"); chain.addPathDefinition("/t5/guest", "anon"); //除了以上的请求外,其它请求都需要登录 chain.addPathDefinition("/**", "authc"); return chain; }
方式2:
@Bean public ShiroFilterFactoryBean ShiroFilterFactoryBean(){ ShiroFilterFactoryBean sb = new ShiroFilterFactoryBean(); sb.setFilterChainDefinitionMap(); sb.setFilters(xx); sb.setLoginUrl(xx); sb.setSecurityManager(xx); sb.setSuccessUrl(xx); sb.setUnauthorizedUrl(xx); return sb; }
其中第二种方法提供的bean对应的默认配置如下:
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.shiro.spring.config.web.autoconfigure; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.spring.web.config.AbstractShiroWebFilterConfiguration; import org.apache.shiro.web.servlet.AbstractShiroFilter; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @since 1.4.0 */ @Configuration @ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true) public class ShiroWebFilterConfiguration extends AbstractShiroWebFilterConfiguration { @Bean @ConditionalOnMissingBean @Override protected ShiroFilterFactoryBean shiroFilterFactoryBean() { //通过方式二覆盖此处的配置 //通过方式二覆盖此处的配置 //通过方式二覆盖此处的配置 //通过方式二覆盖此处的配置 //通过方式二覆盖此处的配置 //通过方式二覆盖此处的配置 //通过方式二覆盖此处的配置 return super.shiroFilterFactoryBean(); } @Bean(name = "filterShiroFilterRegistrationBean") @ConditionalOnMissingBean protected FilterRegistrationBean filterShiroFilterRegistrationBean() throws Exception { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter((AbstractShiroFilter) shiroFilterFactoryBean().getObject()); filterRegistrationBean.setOrder(1); return filterRegistrationBean; } }
3. 自定义密码匹配器
/** * 密码匹配器用于把传入的明文密码安装一定的算法加密成密文,有了密文才能和数据库中存储的密文密码进行比对 * 密码匹配器在认证的时候自动被使用。 */ @Bean(name = "hashedCredentialsMatcher") public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("MD5");// 散列算法:这里使用MD5算法; hashedCredentialsMatcher.setHashIterations(1024);// 散列的次数,比如散列两次,相当于 md5(md5("")); return hashedCredentialsMatcher; }
4. 设置密码匹配器
方式1:在定义realm的时候设置密码匹配器
@Bean public Realm realm() { CustomRealm customRealm = new CustomRealm(); // 方式1:可以在自定义realm的时候设置密码匹配器 customRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return customRealm; }
方式2:在realm类中,通过代码块的形式初始化密码匹配器
public class CustomRealm extends AuthorizingRealm { @Autowired private UserService userService; @Autowired private RoleService roleService; @Autowired private PermService permService; // 方式2: 通过代码类的代码块来初始化密码匹配器,不过这种方式有点丑 { //设置用于匹配密码的CredentialsMatcher HashedCredentialsMatcher hashMatcher = new HashedCredentialsMatcher(); hashMatcher.setHashAlgorithmName(Sha256Hash.ALGORITHM_NAME); hashMatcher.setStoredCredentialsHexEncoded(false); hashMatcher.setHashIterations(1024); this.setCredentialsMatcher(hashMatcher); } // other code }
5. 如果密码中使用了盐值加密,盐值可以通过 ByteSource.Util.bytes(“盐是随机字符串或者username,一般是唯一的”); ,获得盐值后再real认证的时候返回的AuthenticationInfo就应该使用SimpleAuthenticationInfo最复杂的构造方法传入盐值。
6. shiro中默认的过滤器,需要查看org.apache.shiro.web.filter.mgt.DefaultFilter
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.shiro.web.filter.mgt; import org.apache.shiro.util.ClassUtils; import org.apache.shiro.web.filter.authc.*; import org.apache.shiro.web.filter.authz.*; import org.apache.shiro.web.filter.session.NoSessionCreationFilter; import javax.servlet.Filter; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import java.util.LinkedHashMap; import java.util.Map; /** * Enum representing all of the default Shiro Filter instances available to web applications. Each filter instance is * typically accessible in configuration the {@link #name() name} of the enum constant. * * @since 1.0 */ public enum DefaultFilter { anon(AnonymousFilter.class), authc(FormAuthenticationFilter.class), authcBasic(BasicHttpAuthenticationFilter.class), logout(LogoutFilter.class), noSessionCreation(NoSessionCreationFilter.class), perms(PermissionsAuthorizationFilter.class), port(PortFilter.class), rest(HttpMethodPermissionFilter.class), roles(RolesAuthorizationFilter.class), ssl(SslFilter.class), user(UserFilter.class); private final Class<? extends Filter> filterClass; private DefaultFilter(Class<? extends Filter> filterClass) { this.filterClass = filterClass; } public Filter newInstance() { return (Filter) ClassUtils.newInstance(this.filterClass); } public Class<? extends Filter> getFilterClass() { return this.filterClass; } public static Map<String, Filter> createInstanceMap(FilterConfig config) { Map<String, Filter> filters = new LinkedHashMap<String, Filter>(values().length); for (DefaultFilter defaultFilter : values()) { Filter filter = defaultFilter.newInstance(); if (config != null) { try { filter.init(config); } catch (ServletException e) { String msg = "Unable to correctly init default filter instance of type " + filter.getClass().getName(); throw new IllegalStateException(msg, e); } } filters.put(defaultFilter.name(), filter); } return filters; } }
浙公网安备 33010602011771号