github:https://github.com/peterowang/shiro-cas

本文如有配置问题,请查看之前的springboot集成shiro的文章

1.配置ehcache缓存,在resource下创建config,再创建ehcache-shiro.xml添加:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shiroCache"> <defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
</ehcache> 2.添加maven依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-cas</artifactId>
<version>1.2.4</version>
</dependency>
3.配置shiro+cas
添加
MyShiroCasRealm 类
package com.example.demo.config.shiro;

import com.example.demo.model.UserInfo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cas.CasRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import javax.annotation.PostConstruct; /**
* Created by BFD-593 on 2017/8/11.
*/
public class MyShiroCasRealm extends CasRealm {
private static final Logger logger = LoggerFactory.getLogger(MyShiroCasRealm.class);
@PostConstruct
public void initProperty(){
// cas地址
setCasServerUrlPrefix(ShiroConfiguration.casServerUrlPrefix);
// 客户端回调地址
setCasService(ShiroConfiguration.shiroServerUrlPrefix + ShiroConfiguration.casFilterUrlPattern);
} // /**
// * 1、CAS认证 ,验证用户身份
// * 2、将用户基本信息设置到会话中(不用了,随时可以获取的)
// */
// @Override
// protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
//
// AuthenticationInfo authc = super.doGetAuthenticationInfo(token);
//
// String account = (String) authc.getPrincipals().getPrimaryPrincipal();
//
// User user = userDao.getByName(account);
// //将用户信息存入session中
// SecurityUtils.getSubject().getSession().setAttribute("user", user);
//
// return authc;
// } /**
* 此方法调用 hasRole,hasPermission的时候才会进行回调.
*
* 权限信息.(授权): 1、如果用户正常退出,缓存自动清空; 2、如果用户非正常退出,缓存自动清空;
* 3、如果我们修改了用户的权限,而用户不退出系统,修改的权限无法立即生效。 (需要手动编程进行实现;放在service进行调用)
* 在权限修改后调用realm中的方法,realm已经由spring管理,所以从spring中获取realm实例, 调用clearCached方法;
* :Authorization 是授权访问控制,用于对用户进行的操作授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等。
*
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
logger.info("开始权限配置");
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
// UserInfo userInfo = (UserInfo)principals.getPrimaryPrincipal();
//这里应该查询数据库,拿到用户的所有角色,遍历添加角色到权限对象中,再通过角色获取权限,添加到权限对象中
/* for (Role role: userInfo.getRoleList()) {
authorizationInfo.addRole(role.getRole());
for (SysPermission p: role.getPermissions()) {
authorizationInfo.addStringPermission(p.getPermission());
}
}*/
//为了节省时间,这边我先给它写死,做测试
authorizationInfo.addRole("wangjing");
authorizationInfo.addStringPermission("userinfo:view");
return authorizationInfo;
}
} 添加shiro配置类,主要是将casFilter添加到shiroFilter中
package com.example.demo.config.shiro;

import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.cas.CasFilter;
import org.apache.shiro.cas.CasSubjectFactory;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.session.SingleSignOutHttpSessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties; /**
* shiro配置类
* Created by BFD-593 on 2017/8/8.
*/
@Configuration
public class ShiroConfiguration {
private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);
// cas server地址
public static final String casServerUrlPrefix = "https://localhost:8443/cas";
// Cas登录页面地址
public static final String casLoginUrl = casServerUrlPrefix + "/login";
// Cas登出页面地址
public static final String casLogoutUrl = casServerUrlPrefix + "/logout";
// 当前工程对外提供的服务地址
public static final String shiroServerUrlPrefix = "http://localhost:8089";
// casFilter UrlPattern
public static final String casFilterUrlPattern = "/cas";
// 登录地址
public static final String loginUrl = casLoginUrl + "?service=" + shiroServerUrlPrefix + casFilterUrlPattern;
// 登出地址(casserver启用service跳转功能,需在webapps\cas\WEB-INF\cas.properties文件中启用cas.logout.followServiceRedirects=true)
public static final String logoutUrl = casLogoutUrl+"?service="+shiroServerUrlPrefix;
// 登录成功地址
public static final String loginSuccessUrl = "/index";
// 权限认证失败跳转地址
public static final String unauthorizedUrl = "/403";
@Bean
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml");
return em;
} @Bean(name = "myShiroCasRealm")
public MyShiroCasRealm myShiroCasRealm(EhCacheManager cacheManager) {
MyShiroCasRealm realm = new MyShiroCasRealm();
realm.setCacheManager(cacheManager);
return realm;
} /**
* 注册单点登出listener
* @return
*/
@Bean
public ServletListenerRegistrationBean singleSignOutHttpSessionListener(){
ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();
bean.setListener(new SingleSignOutHttpSessionListener());
bean.setEnabled(true);
return bean;
} /**
* 注册单点登出filter
* @return
*/
@Bean
public FilterRegistrationBean singleSignOutFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setName("singleSignOutFilter");
bean.setFilter(new SingleSignOutFilter());
bean.addUrlPatterns("/*");
bean.setEnabled(true);
return bean;
} /**
* 注册DelegatingFilterProxy(Shiro)
*/
@Bean
public FilterRegistrationBean delegatingFilterProxy() {
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(@Qualifier("myShiroCasRealm") MyShiroCasRealm myShiroCasRealm) {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(myShiroCasRealm);
//用户授权/认证信息Cache, 采用EhCache 缓存
dwsm.setCacheManager(getEhCacheManager());
// 指定 SubjectFactory
dwsm.setSubjectFactory(new CasSubjectFactory());
return dwsm;
} /**
* CAS过滤器
*
* @return
*/
@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
* @param securityManager
* @param casFilter
* @return
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager,
@Qualifier("casFilter") CasFilter casFilter) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl(loginUrl);
// 登录成功后要跳转的连接
shiroFilterFactoryBean.setSuccessUrl(loginSuccessUrl);
shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
// 添加casFilter到shiroFilter中
Map<String, Filter> filters = new HashMap<>();
filters.put("casFilter", casFilter);
shiroFilterFactoryBean.setFilters(filters); loadShiroFilterChain(shiroFilterFactoryBean);
return shiroFilterFactoryBean;
} /**
* 加载shiroFilter权限控制规则(从数据库读取然后配置),角色/权限信息由MyShiroCasRealm对象提供doGetAuthorizationInfo实现获取来的
*/
private void loadShiroFilterChain(@Qualifier("shiroFilter") ShiroFilterFactoryBean shiroFilterFactoryBean){
/////////////////////// 下面这些规则配置最好配置到配置文件中 ///////////////////////
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); // authc:该过滤器下的页面必须登录后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter
// anon: 可以理解为不拦截
// user: 登录了就不拦截
// roles["admin"] 用户拥有admin角色
// perms["permission1"] 用户拥有permission1权限
// filter顺序按照定义顺序匹配,匹配到就验证,验证完毕结束。
// url匹配通配符支持:? * **,分别表示匹配1个,匹配0-n个(不含子路径),匹配下级所有路径 //1.shiro集成cas后,首先添加该规则
filterChainDefinitionMap.put(casFilterUrlPattern, "casFilter"); //2.不拦截的请求
filterChainDefinitionMap.put("/css/**","anon");
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/logout","anon");
filterChainDefinitionMap.put("/error","anon"); //3.拦截的请求,并且拥有哪些权限才可以访问,当没有权限时
// 我们通过在shiroFilter里设置 shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
// 让其跳转到403页面,需要加403的controller请求哦
// 这里还可以通过另一种方式,就是在controller的需要的请求上,加shiro的权限注解
// 如果通过注解的方式,则需要通过以下两个配置bean来分别设置支持shiro注解和无权限跳转的页面
filterChainDefinitionMap.put("/userinfo/userList", "authc,perms[\"userinfo:view\"],roles[\"wangjing\"]"); //需要登录,且用户有权限为userinfo:view并且角色为wangjing
filterChainDefinitionMap.put("/userinfo/userDel", "authc,perms[\"userinfo:view\"],roles[\"admin\"]");
filterChainDefinitionMap.put("/userinfo/userAdd", "authc,perms[\"userinfo:view\"],roles[\"redhat\"]");
//4.登录过的不拦截
filterChainDefinitionMap.put("/**", "user");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
}
/*
*//**
* 权限认证
* 需要开启Shiro AOP注解支持
* @RequiresPermissions({"userinfo:view"})
* @RequiresRoles({"wangjing"})等注解的支持
* @param securityManager
* @return
*//*
@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(securityManager);
return aasa;
}*/
/**
* 当用户无权限访问403页面而不抛异常,默认shiro会报UnauthorizedException异常
* @return
*/
/* @Bean
public SimpleMappingExceptionResolver resolver() {
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties properties = new Properties();
properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/403");
resolver.setExceptionMappings(properties);
return resolver;
}*/
} 添加HomeController
package com.example.demo.web;

import com.example.demo.config.shiro.ShiroConfiguration;
import com.example.demo.model.UserInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.http.HttpSession; /**
* Created by BFD-593 on 2017/8/8.
*/
@Controller
public class HomeController {
private static final Logger log = LoggerFactory.getLogger(HomeController.class);
@RequestMapping({"/","/index"})
public String index() {
return "index";
} /**
* shiroFilterFactoryBean.setLoginUrl(loginUrl);我们设置了登录地址,但没设置logout,
* 所以加一个logout的请求,转到cas的logout上
* @param session
* @return
*/
@RequestMapping(value = "logout", method = { RequestMethod.GET,
RequestMethod.POST })
public String loginout(HttpSession session)
{
return "redirect:"+ShiroConfiguration.logoutUrl;
}
@RequestMapping("/403")
public String fail(){
return "403";
}
} 添加UserController
package com.example.demo.web;

import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; /**
* Created by BFD-593 on 2017/8/9.
*/
@Controller
@RequestMapping("/userinfo")
public class UserController {
/**
* 要查看必须有角色wangjing和有权限userinfo:view
* @return
*/
@RequestMapping("/userList")
public String userInfo(){
return "userInfo";
} /**
* 用户添加必须有查看和删除权限;
* @return
*/
@RequestMapping("/userAdd")
public String userInfoAdd(){
return "userAdd";
} /**
* 要删除必须有查看和删除权限
* @return
*/
@RequestMapping("/userDel")
public String userInfoDel() {
return "userDel";
} }

运行验证

登录

访问:http://localhost:8089

跳转至:https://localhost:8443/cas/login?service=http://localhost:8089/cas

输入正确用户名密码登录跳转回:http://localhost:8089/cas?ticket=ST-203-GUheN64mOZec9IWZSH1B-cas01.example.org

最终跳回:http://localhost:8089/index

登出

访问:http://localhost:8089/logout

跳转至:https://localhost:8443/cas/logout?service=http://localhost:8089/cas

这次登录成功后返回:http://localhost:8089/index

springboot+shiro+cas实现单点登录之shiro端搭建的更多相关文章

  1. [精华][推荐]CAS SSO 单点登录框架学习 环境搭建

    1.了解单点登录  SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) ,并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用( ...

  2. springboot+shiro+cas实现单点登录之cas server搭建

    CAS是YALE大学发起的一个开源项目,旨在为web应用系统提供一种可靠的单点登录方法.它主要分为client和server端,server端负责对用户的认证工作,client端负责处理对客户端受保护 ...

  3. CAS5.3服务器搭建及SpringBoot整合CAS实现单点登录

    1.1 什么是单点登录 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的 ...

  4. cas sso单点登录系列3_cas-server端配置认证方式实践(数据源+自定义java类认证)

    转:http://blog.csdn.net/ae6623/article/details/8851801 本篇将讲解cas-server端的认证方式 1.最简单的认证,用户名和密码一致就登录成功 2 ...

  5. cas+tomcat+shiro实现单点登录-4-Apache Shiro 集成Cas作为cas client端实现

    目录 1.tomcat添加https安全协议 2.下载cas server端部署到tomcat上 3.CAS服务器深入配置(连接MYSQL) 4.Apache Shiro 集成Cas作为cas cli ...

  6. 如何利用tomcat和cas实现单点登录(1):配置tomcat的ssl和部署cas

    如何利用tomcat和cas实现单点登录,借鉴了网上的很多教程,主要分为以下几个步骤: 一:下载好cas,tomcat之后,首先配置tomcat: 用鼠标右键点击"计算机"→选择& ...

  7. CAS实现单点登录流程

    CAS实现单点登录 环境 客户端: www.app1.com CAS服务器: www.cas-server.com 1.浏览器:发起请求 www.app1.com 2. 客户端:Authenticat ...

  8. CAS实现单点登录SSO执行原理及部署

    一.不落俗套的开始 1.背景介绍 单点登录:Single Sign On,简称SSO,SSO使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. CAS框架:CAS(Centra ...

  9. CAS SSO单点登录框架学习

    1.了解单点登录  SSO 主要特点是: SSO 应用之间使用 Web 协议(如 HTTPS) ,并且只有一个登录入口. SSO 的体系中有下面三种角色: 1) User(多个) 2) Web 应用( ...

随机推荐

  1. configured to save RDB snapshots, but is currently not able to persist o...

    Redis问题 MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on d ...

  2. Floyd(稠密图,记录路径)

    #include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #i ...

  3. python+ mysql存储二进制流的方式

    很多时候我们为了管理方便会把依稀很小的图片存入数据库,有人可能会想这样会不会对数据库造成很大的压力,其实大家可以不用担心,因为我说过了,是存储一些很小的图片,几K的,没有问题的! 再者,在这里我们是想 ...

  4. 网络编程 recv()函数

    recv()是编程语言函数. 函数原型int recv( _In_ SOCKET s, _Out_ char *buf, _In_ int len, _In_ int flags); 这里只描述同步S ...

  5. POJ-3187

    Backward Digit Sums Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7634   Accepted: 43 ...

  6. Java socket异常

    Java socket异常 分类: Java 2013-07-15 22:38 981人阅读 评论(0) 收藏 举报 目录(?)[+] 使用Java socket编写程序时,通常会遇到几种种异常:Bi ...

  7. 萌新笔记之Nim取石子游戏

    以下笔记摘自计算机丛书组合数学,机械工业出版社. Nim取石子游戏 Nim(来自德语Nimm!,意为拿取)取石子游戏. 前言: 哇咔咔,让我们来追寻娱乐数学的组合数学起源! 游戏内容: 有两个玩家面对 ...

  8. Codeforces Round #401 (Div. 2)【A,B,C,D】

    最近状态极差..水题不想写,难题咬不动..哎,CF的题那么简单,还搞崩了= =.真是巨菜无比. Codeforces777A 题意:略. 思路: 构造出3!次变换,然后输出就好. Code: #inc ...

  9. CentOS 安装配置vncserver

    yum 安装tiger vncserver yum install tigervnc-server 安装后输入 vncserver 设置密码 3.配置用户 vim /etc/sysconfig/vnc ...

  10. Js 验证时间格式是否正确

    function RQcheck(RQ) { var date = RQ; //(-|\/)分隔符 var result = date.match(/^(\d{1,4})(-|\/)(\d{1,2}) ...