1.pom 文件
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
2.配置中心
/*@Configuration*/ public class ShiroConfig { /**** * 拦截器配置 * @param securityManager * @return */ @Bean public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //拦截器 Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>(); //配置不会被拦截的连接 顺序判断 filterChainDefinitionMap.put("/static/**","anon"); //配置退出 过滤器 filterChainDefinitionMap.put("/logout","logout"); filterChainDefinitionMap.put("/**","authc"); shiroFilterFactoryBean.setSuccessUrl("/index"); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setUnauthorizedUrl("/403"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } /*** * 凭证匹配器 * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了) * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher(){ HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5"); hashedCredentialsMatcher.setHashIterations(1024); return hashedCredentialsMatcher; } @Bean public MyShiroRealm myShiroRealm(){ MyShiroRealm myShiroRealm = new MyShiroRealm(); myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; } /*** * securityManger 配置 * @return */ @Bean public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); return securityManager; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; }
3.realm 文件
//用户方法 @Autowired IUserService userService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()"); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); User user = (User) principals.getPrimaryPrincipal(); for (Role role:user.getRoleList()){ authorizationInfo.addRole(role.getEnname()); for (Menu p:role.getPermissions()){ authorizationInfo.addStringPermission(p.getPermission()); } } return authorizationInfo; } /*主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token){ //获取用户输入的账号 String username = (String) token.getPrincipal(); System.out.println(token.getCredentials()); User user = userService.findByLoginName(username); if (user == null){ return null; } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( user, user.getPassword(), ByteSource.Util.bytes(user.getUsername()), getName() ); return authenticationInfo;
}
}
3.shiro + cas
@Configuration public class ShiroCasConfiguration { private static final Logger logger = LoggerFactory.getLogger(ShiroCasConfiguration.class); // CasServerUrlPrefix public static final String casServerUrlPrefix = "http://182.61.10.117:8080/cas"; // Cas登录页面地址 public static final String casLoginUrl = casServerUrlPrefix + "/login"; // Cas登出页面地址 public static final String casLogoutUrl = casServerUrlPrefix + "/logout"; // 当前工程对外提供的服务地址 public static final String shiroServerUrlPrefix = "http://localhost:8086/shiro"; // casFilter UrlPattern public static final String casFilterUrlPattern = "/index"; // 登录地址 public static final String loginUrl = casLoginUrl + "?service=" + shiroServerUrlPrefix + casFilterUrlPattern; @Bean public EhCacheManager getEhCacheManager() { EhCacheManager em = new EhCacheManager(); em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml"); return em; } @Bean(name = "myShiroCasRealm") public CasShiroRealm myShiroCasRealm(EhCacheManager cacheManager) { CasShiroRealm realm = new CasShiroRealm(); realm.setCacheManager(cacheManager); return realm; } /** * 注册DelegatingFilterProxy(Shiro) * * @param * @return */ @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistration = new FilterRegistrationBean(); filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter")); // 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 filterRegistration.addInitParameter("targetFilterLifecycle", "true"); filterRegistration.setEnabled(true); filterRegistration.addUrlPatterns("/*"); return filterRegistration; } @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator(); daap.setProxyTargetClass(true); return daap; } @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(CasShiroRealm myShiroCasRealm) { DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager(); dwsm.setRealm(myShiroCasRealm); // <!-- 用户授权/认证信息Cache, 采用EhCache 缓存 --> dwsm.setCacheManager(getEhCacheManager()); // 指定 SubjectFactory dwsm.setSubjectFactory(new CasSubjectFactory()); return dwsm; } @Bean public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor(); aasa.setSecurityManager(securityManager); return aasa; } /** * 加载shiroFilter权限控制规则(从数据库读取然后配置) * * @author SHANHY * @create 2016年1月14日 */ private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean){ /// 下面这些规则配置最好配置到配置文件中 /// Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); filterChainDefinitionMap.put(casFilterUrlPattern, "casFilter");// shiro集成cas后,首先添加该规则 // authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter /* filterChainDefinitionMap.put("/user", "authc");// 这里为了测试,只限制/user,实际开发中请修改为具体拦截的请求规则 */ // anon:它对应的过滤器里面是空的,什么都没做 logger.info("##################从数据库读取权限规则,加载到shiroFilter中##################"); /* filterChainDefinitionMap.put("/user/edit/**", "authc,perms[user:edit]");// 这里为了测试,固定写死的值,也可以从数据库或其他配置中读取*/ filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/403","anon"); filterChainDefinitionMap.put("/**", "authc");//anon 可以理解为不拦截 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); } /** * CAS过滤器 * */ @Bean(name = "casFilter") public CasFilter getCasFilter() { CasFilter casFilter = new CasFilter(); casFilter.setName("casFilter"); casFilter.setEnabled(true); // 登录失败后跳转的URL,也就是 Shiro 执行 CasRealm 的 doGetAuthenticationInfo 方法向CasServer验证tiket casFilter.setFailureUrl(loginUrl);// 我们选择认证失败后再打开登录页面 return casFilter; } /** * ShiroFilter<br/> * 注意这里参数中的 StudentService 和 IScoreDao 只是一个例子,因为我们在这里可以用这样的方式获取到相关访问数据库的对象, * 然后读取数据库相关配置,配置到 shiroFilterFactoryBean 的访问规则中。实际项目中,请使用自己的Service来处理业务逻辑。 * @return */ @Bean(name = "shiroFilter") public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager, CasFilter casFilter) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必须设置 SecurityManager shiroFilterFactoryBean.setSecurityManager(securityManager); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl(loginUrl); // 登录成功后要跳转的连接 shiroFilterFactoryBean.setSuccessUrl("/index"); shiroFilterFactoryBean.setUnauthorizedUrl("/403"); // 添加casFilter到shiroFilter中 Map<String, Filter> filters = new HashMap<>(); filters.put("casFilter", casFilter); shiroFilterFactoryBean.setFilters(filters); loadShiroFilterChain(shiroFilterFactoryBean); return shiroFilterFactoryBean; }
4.realm
public class CasShiroRealm extends CasRealm { //用户方法 @Autowired IUserService userService; private static final Logger logger = LoggerFactory.getLogger(CasShiroRealm.class); @PostConstruct public void initProperty(){ // setDefaultRoles("ROLE_USER"); setCasServerUrlPrefix(ShiroCasConfiguration.casServerUrlPrefix); // 客户端回调地址 setCasService(ShiroCasConfiguration.shiroServerUrlPrefix + ShiroCasConfiguration.casFilterUrlPattern); } /** */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { logger.info("##################执行Shiro权限认证##################"); //获取当前登录输入的用户名,等价于(String) principalCollection.fromRealm(getName()).iterator().next(); String loginName = (String)super.getAvailablePrincipal(principalCollection); //到数据库查是否有此对象 User user=userService.findByLoginName(loginName);// 实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法 if(user!=null){ SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); for (Role role:user.getRoleList()){ authorizationInfo.addRole(role.getEnname()); for (Menu p:role.getPermissions()){ authorizationInfo.addStringPermission(p.getPermission()); } } return authorizationInfo; } // 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedUrl指定的地址 return null; } }