springboot + shiro + cas4.2.7 实战
1. 下载地址 https://github.com/apereo/cas/archive/v4.2.7.zip
2. 解压后, 用intellj idea 打开
3. 执行 gradle build -x test ,打包编译
4. 取消https,能够支持直接http
cas.properties 修改两个地方
# Decides whether SSO cookie should be created only under secure connections.
tgc.secure=false # The expiration value of the SSO cookie
# tgc.maxAge=-1 # The name of the SSO cookie
# tgc.name=TGC # The path to which the SSO cookie will be scoped
# tgc.path=/cas # The expiration value of the SSO cookie for long-term authentications
# tgc.remember.me.maxAge=1209600 # Decides whether SSO Warning cookie should be created only under secure connections.
warn.cookie.secure=false
casLoginView.jsp
<jsp:directive.include file="includes/top.jsp" /> <%--<c:if test="${not pageContext.request.secure}">
<div id="msg" class="errors">
<h2><spring:message code="screen.nonsecure.title" /></h2>
<p><spring:message code="screen.nonsecure.message" /></p>
</div>
</c:if>--%>
注销上面的代码
HTTPSandIMAPS-10000001.json 中增加http的service
{
"@class" : "org.jasig.cas.services.RegexRegisteredService",
"serviceId" : "^(https|imaps|http)://.*",
"name" : "HTTPS and IMAPS",
"id" : 10000001,
"description" : "This service definition authorized all application urls that support HTTPS and IMAPS protocols.",
"proxyPolicy" : {
"@class" : "org.jasig.cas.services.RefuseRegisteredServiceProxyPolicy"
},
"evaluationOrder" : 10000,
"usernameAttributeProvider" : {
"@class" : "org.jasig.cas.services.DefaultRegisteredServiceUsernameProvider"
},
"logoutType" : "BACK_CHANNEL",
"attributeReleasePolicy" : {
"@class" : "org.jasig.cas.services.ReturnAllowedAttributeReleasePolicy",
"principalAttributesRepository" : {
"@class" : "org.jasig.cas.authentication.principal.DefaultPrincipalAttributesRepository"
},
"authorizedToReleaseCredentialPassword" : false,
"authorizedToReleaseProxyGrantingTicket" : false
},
"accessStrategy" : {
"@class" : "org.jasig.cas.services.DefaultRegisteredServiceAccessStrategy",
"enabled" : true,
"ssoEnabled" : true
}
}
5. 修改cas的认证方式,包括jdbc、 自定义密码加密等
5.1 修改 cas-server-webapp 的依赖,修改 该工程下build.gradle
5.2 修改cas.properties
cas.jdbc.authn.query.sql=SELECT username,pwd,salt,`status` FROM sys_user WHERE username = ?
cas.jdbc.authn.search.password=root
cas.jdbc.authn.search.user=root
5.3 自定义密码加密 CustomEncoder
package org.jasig.cas.adaptors.jdbc; import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Value; /**
* Created by 肖建锋 on 2017/3/25.
*/
public class CustomEncoder {
/** 随机字符生产工具 */
private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator(); /** 加密方式 */
private String algorithmName = "sha"; /** 多重加密次数 */
private int hashIterations = 2; /**
* 配置随机字符生产工具
* @param randomNumberGenerator
*
* @author xiaojf 2016-01-07 01:46
*/
public void setRandomNumberGenerator(RandomNumberGenerator randomNumberGenerator) {
this.randomNumberGenerator = randomNumberGenerator;
} /**
* 配置加密方式
* @param algorithmName
*
* @author xiaojf 2016-01-07 01:46
*/
public void setAlgorithmName(String algorithmName) {
this.algorithmName = algorithmName;
} /**
* 配置重复加密次数
* @param hashIterations
*
* @author xiaojf 2016-01-07 01:46
*/
public void setHashIterations(int hashIterations) {
this.hashIterations = hashIterations;
} /**
* 密码加密
* @param pwd
* @param salt
* @author xiaojf 2016-01-07 01:46
*/
public String encryptPassword(String pwd,String salt) {
return new SimpleHash(algorithmName, pwd, ByteSource.Util.bytes(salt), hashIterations).toHex();
}
/**
* 根据私钥加密
* @param value 要加密字段
* @param salt 密钥
* @author hp
* @return 加密后字段
* 2016-05-07 01:46
*/
public String encrypt(String value , String salt) {
return new SimpleHash(algorithmName, value, ByteSource.Util.bytes(salt), hashIterations).toHex();
} /**
* 获取加密后的新密码
*
* @param pwd 密码
* @param salt 盐
* @return 新密码
* @author xiaojf 2016-5-7 15:37:54
*/
public String getEncryptPassword(String pwd,String salt){
String newPassword = new SimpleHash(algorithmName, pwd, ByteSource.Util.bytes(salt), hashIterations).toHex(); return newPassword;
} /**
* @param args the input arguments
* @author xiaojf 2016-5-7 15:37:54
*/
public static void main(String[] args) {
/*SysUser sysUser = new SysUser();
sysUser.setUsername("super");
sysUser.setPwd("admin");*/
String s = new CustomEncoder().encrypt("super","e910c85b7f5c5e789d50fafcfa5d4efc");
System.out.println(s);
}
}
5.4 自定义用户认证方式
package org.jasig.cas.adaptors.jdbc; import org.apache.commons.lang3.StringUtils;
import org.jasig.cas.authentication.HandlerResult;
import org.jasig.cas.authentication.PreventedException;
import org.jasig.cas.authentication.UsernamePasswordCredential;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Component; import javax.security.auth.login.AccountNotFoundException;
import javax.security.auth.login.FailedLoginException;
import javax.sql.DataSource;
import javax.validation.constraints.NotNull;
import java.security.GeneralSecurityException;
import java.util.Map; /**
* Class that if provided a query that returns a password (parameter of query
* must be username) will compare that password to a translated version of the
* password provided by the user. If they match, then authentication succeeds.
* Default password translator is plaintext translator.
*
* @author Scott Battaglia
* @author Dmitriy Kopylenko
* @author Marvin S. Addison
*
* @since 3.0.0
*/
@Component("queryDatabaseAuthenticationHandler2")
public class QueryDatabaseAuthenticationHandler2 extends AbstractJdbcUsernamePasswordAuthenticationHandler { @NotNull
private String sql; @Override
protected final HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential)
throws GeneralSecurityException, PreventedException { if (StringUtils.isBlank(this.sql) || getJdbcTemplate() == null) {
throw new GeneralSecurityException("Authentication handler is not configured correctly");
} final String username = credential.getUsername();
try {
Map<String, Object> map = getJdbcTemplate().queryForMap(sql, username);
final String dbPassword = map.get("pwd")+"";
String salt = map.get("salt")+"";
int status = Integer.parseInt(map.get("status")+"");
final String encryptedPassword = new CustomEncoder().encryptPassword(credential.getPassword(),salt); if (!dbPassword.equals(encryptedPassword)) {
throw new FailedLoginException("Password does not match value on record.");
}
} catch (final IncorrectResultSizeDataAccessException e) {
if (e.getActualSize() == 0) {
throw new AccountNotFoundException(username + " not found with SQL query");
} else {
throw new FailedLoginException("Multiple records found for " + username);
}
} catch (final DataAccessException e) {
throw new PreventedException("SQL exception while executing query for " + username, e);
}
return createHandlerResult(credential, this.principalFactory.createPrincipal(username), null);
} /**
* @param sql The sql to set.
*/
@Autowired
public void setSql(@Value("${cas.jdbc.authn.query.sql:}") final String sql) {
this.sql = sql;
} @Override
@Autowired(required = false)
public void setDataSource(@Qualifier("queryDatabaseDataSource") final DataSource dataSource) {
super.setDataSource(dataSource);
}
}
6. 自定义数据源
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!-- 设置druid数据源 -->
<bean id="queryDatabaseDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="url" value="jdbc:mysql://localhost:3306/tomorrow?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean> </beans>
7. 修改 cas默认的用户校验方式,注入我们上面定义的规则 deployerConfigContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <util:map id="authenticationHandlersResolvers">
<entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />
</util:map> <util:list id="authenticationMetadataPopulators">
<ref bean="successfulHandlerMetaDataPopulator" />
<ref bean="rememberMeAuthenticationMetaDataPopulator" />
</util:list> <bean id="attributeRepository" class="org.jasig.services.persondir.support.NamedStubPersonAttributeDao"
p:backingMap-ref="attrRepoBackingMap" /> <alias name="queryDatabaseAuthenticationHandler2" alias="primaryAuthenticationHandler" />
<alias name="personDirectoryPrincipalResolver" alias="primaryPrincipalResolver" /> <util:map id="attrRepoBackingMap">
<entry key="uid" value="uid" />
<entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
<entry key="groupMembership" value="groupMembership" />
<entry>
<key><value>memberOf</value></key>
<list>
<value>faculty</value>
<value>staff</value>
<value>org</value>
</list>
</entry>
</util:map> <alias name="serviceThemeResolver" alias="themeResolver" /> <alias name="jsonServiceRegistryDao" alias="serviceRegistryDao" /> <alias name="defaultTicketRegistry" alias="ticketRegistry" /> <alias name="ticketGrantingTicketExpirationPolicy" alias="grantingTicketExpirationPolicy" />
<alias name="multiTimeUseOrTimeoutExpirationPolicy" alias="serviceTicketExpirationPolicy" /> <alias name="anyAuthenticationPolicy" alias="authenticationPolicy" />
<alias name="acceptAnyAuthenticationPolicyFactory" alias="authenticationPolicyFactory" /> <bean id="auditTrailManager"
class="org.jasig.inspektr.audit.support.Slf4jLoggingAuditTrailManager"
p:entrySeparator="${cas.audit.singleline.separator:|}"
p:useSingleLine="${cas.audit.singleline:false}"/> <alias name="neverThrottle" alias="authenticationThrottle" /> <util:list id="monitorsList">
<ref bean="memoryMonitor" />
<ref bean="sessionMonitor" />
</util:list> <alias name="defaultPrincipalFactory" alias="principalFactory" />
<alias name="defaultAuthenticationTransactionManager" alias="authenticationTransactionManager" />
<alias name="defaultPrincipalElectionStrategy" alias="principalElectionStrategy" />
<alias name="tgcCipherExecutor" alias="defaultCookieCipherExecutor" /> </beans>
8. 打war包,复制到tomcat下启动,或者直接用idea运行
到这里cas安装修改完成了,接下来是修改springboot+shiro + cas(重点部分,已经用红色标出)
9. 加入shiro-cas依赖
compile ("org.apache.shiro:shiro-cas:1.3.2")
10. 修改 ShiroConfiguration.java 自定义cas filter
@Bean
public CasFilter casFilter() {
CasFilter casFilter = new CasFilter();
casFilter.setFailureUrl("/error/403");
casFilter.setSuccessUrl("/");
return casFilter;
}
11. 自定义 cas realm
@Bean
public MyCasRealm myCasRealm(RetryLimitHashedCredentialsMatcher credentialsMatcher) {
MyCasRealm casRealm = new MyCasRealm();
casRealm.setCachingEnabled(true); casRealm.setCasServerUrlPrefix("http://localhost:8080/cas");
casRealm.setCasService("http://localhost:8000/shiro-cas"); return casRealm;
}
12. 自定义多点登出逻辑,不能使用shiro自带的logout filter
package cn.xiaojf.today.sys.web.controller; import cn.xiaojf.today.base.constant.SystemConstant;
import cn.xiaojf.today.base.model.CommonResult;
import cn.xiaojf.today.base.exception.BusinessException;
import cn.xiaojf.today.base.web.controller.BaseController;
import cn.xiaojf.today.log.OperationType;
import cn.xiaojf.today.log.annotation.OperateLog;
import cn.xiaojf.today.sys.entity.SysUser;
import cn.xiaojf.today.sys.service.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.session.HttpServletSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpSession;
import java.util.Set; /**
* @author xiaojf 2017/2/9 15:48.
*/
@RestController
@RequestMapping("/login")
public class LoginController {
@Autowired
private SysUserService userService; Logger logger = LoggerFactory.getLogger(LoginController.class); @RequestMapping("index")
public ModelAndView index() {
ModelAndView mv = new ModelAndView("/login");
return mv;
} @RequestMapping("out")
public ModelAndView out() {
SecurityUtils.getSubject().logout();
ModelAndView view = new ModelAndView();
view.setViewName("redirect:http://localhost:8080/cas/logout");
return view;
} @RequestMapping("auth")
@OperateLog(module = OperationType.LOGIN)
public ModelAndView auth(String username, String password, boolean rememberMe, HttpSession session) {
ModelAndView mv = new ModelAndView("/");
try {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
subject.login(token); SysUser user = userService.getByUsername(username);
//在session中保存当前用户的个人信息
session.setAttribute(SystemConstant.SYS_CURRENT_USER, user);
//在session中保存用户的r_path
Set<String> rpathSet = userService.loadUserRPath(user.getId());
String rpath = StringUtils.join(rpathSet, SystemConstant.DATA_SPLIT_CHAR);
session.setAttribute(SystemConstant.SYS_CURRENT_USER_RPATH, rpath); } catch (IllegalArgumentException e) {
mv.setViewName("/login/index");
mv.addObject("errMsg","参数异常");
logger.error(e.getMessage(), e.getStackTrace());
} catch (AuthenticationException e) {
logger.error(e.getMessage(), e.getStackTrace());
mv.setViewName("/login/index");
mv.addObject("errMsg","认证失败");
} catch (BusinessException e) {
mv.setViewName("/login/index");
mv.addObject("errMsg","登录异常"); logger.error(e.getMessage(), e.getStackTrace());
} catch (Exception e) {
mv.setViewName("/login/index");
mv.addObject("errMsg","登录异常");
logger.error(e.getMessage(), e.getStackTrace());
}
return mv;
} }
13. 完整的 ShiroConfiguration
package cn.xiaojf.today.shiro.configuration; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import cn.xiaojf.today.sys.security.credentials.RetryLimitHashedCredentialsMatcher;
import cn.xiaojf.today.sys.security.filter.RoleAuthorizationFilter;
import cn.xiaojf.today.sys.security.realm.MyCasRealm;
import cn.xiaojf.today.sys.security.realm.UsernameRealm;
import cn.xiaojf.today.sys.service.SysResService;
import org.apache.shiro.cas.CasFilter;
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.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy; import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map; /**
* shiro配置
* @author xiaojf 2017/2/10 11:30.
*/
@Configuration
public class ShiroConfiguration {
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new DelegatingFilterProxy("shiroFilter"));
filterRegistrationBean.addInitParameter("targetFilterLifecycle", "true");
filterRegistrationBean.setEnabled(true);
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
} @Bean
public RetryLimitHashedCredentialsMatcher credentialsMatcher() {
RetryLimitHashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("sha");
credentialsMatcher.setHashIterations(2);
credentialsMatcher.setStoredCredentialsHexEncoded(true);
credentialsMatcher.setRetryCount(5);
credentialsMatcher.setRetryTime(1800000);
return credentialsMatcher;
} @Bean
public UsernameRealm usernameRealm(RetryLimitHashedCredentialsMatcher credentialsMatcher) {
UsernameRealm usernameRealm = new UsernameRealm();
usernameRealm.setCredentialsMatcher(credentialsMatcher);
usernameRealm.setCachingEnabled(true);
return usernameRealm;
} @Bean
public MyCasRealm myCasRealm(RetryLimitHashedCredentialsMatcher credentialsMatcher) {
MyCasRealm casRealm = new MyCasRealm();
// casRealm.setCredentialsMatcher(credentialsMatcher);
casRealm.setCachingEnabled(true); casRealm.setCasServerUrlPrefix("http://localhost:8080/cas");
casRealm.setCasService("http://localhost:8000/shiro-cas"); return casRealm;
} @Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
} @Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
daap.setProxyTargetClass(true);
return daap;
} /*@Bean
public DefaultWebSecurityManager securityManager(UsernameRealm usernameRealm) {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(usernameRealm);
return dwsm;
}*/ @Bean
public DefaultWebSecurityManager securityManager(MyCasRealm myCasRealm) {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(myCasRealm);
return dwsm;
} @Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(defaultWebSecurityManager);
return aasa;
} @Bean
public CasFilter casFilter() {
CasFilter casFilter = new CasFilter();
casFilter.setFailureUrl("/error/403");
casFilter.setSuccessUrl("/");
return casFilter;
} @Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager, CasFilter casFilter,ApplicationContext context) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("http://localhost:8080/cas/login?service=http://localhost:8000/shiro-cas");
shiroFilterFactoryBean.setUnauthorizedUrl("http://localhost:8080/cas/login?service=http://localhost:8000/shiro-cas"); Map<String, Filter> filters = new LinkedHashMap<>();
filters.put("role", new RoleAuthorizationFilter());
filters.put("cas",casFilter); shiroFilterFactoryBean.getFilters().putAll(filters); SysResService resService = context.getBean(SysResService.class);
loadShiroFilterChain(shiroFilterFactoryBean,resService);
return shiroFilterFactoryBean;
} private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean,SysResService resService) {
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// filterChainDefinitionMap.put("/login/index", "anon");
filterChainDefinitionMap.put("/error/403", "anon");
filterChainDefinitionMap.put("/error/404", "anon");
filterChainDefinitionMap.put("/error/500", "anon");
// filterChainDefinitionMap.put("/login/auth", "anon");
filterChainDefinitionMap.put("login/out", "authc");
filterChainDefinitionMap.put("/plugins/**", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/images/**", "anon"); filterChainDefinitionMap.put("/shiro-cas", "cas"); filterChainDefinitionMap = resService.loadFilterChainDefinitions(filterChainDefinitionMap); filterChainDefinitionMap.put("/**", "role[ROLE_SUPER]"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
} @Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}
14. 修改完成以后, 直接访问自己的项目会自动的跳转到cas的登陆页面,登陆完成后会跳转到自己项目的首页,注意主要是下面这句话的效果
shiroFilterFactoryBean.setLoginUrl("http://localhost:8080/cas/login?service=http://localhost:8000/shiro-cas"); 首先登陆的请求被转发到
http://localhost:8080/cas/login
然后登陆成功会返回ticket,并重定向到
http://localhost:8000/shiro-cas shiro-cas 会通过cas filter 拦截到shiro-cas,然后根据返回的username 对用户进行授权 还有一点需要注意的时候 , cas 默认接受的参数名称是 username, password ,可以在cas.properties 中修改默认, 下面是我的登陆表单代码,仅供参考
<form action="/login/auth" method="post">
<input id="username" type="text" name="username" class="username" placeholder="用户名">
<input id="pwd" type="password" name="pwd" class="password" placeholder="密码">
<button type="submit">登 录</button>
</form>
springboot + shiro + cas4.2.7 实战的更多相关文章
- SpringBoot与Shiro整合权限管理实战
SpringBoot与Shiro整合权限管理实战 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] *观看本文章需要有一定SpringBoot整合经验* Shiro框架简介 Apach ...
- SpringBoot+Shiro+mybatis整合实战
SpringBoot+Shiro+mybatis整合 1. 使用Springboot版本2.0.4 与shiro的版本 引入springboot和shiro依赖 <?xml version=&q ...
- springboot+shiro
作者:纯洁的微笑 出处:http://www.ityouknow.com/ 这篇文章我们来学习如何使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公 ...
- SpringBoot+Shiro+Redis共享Session入门小栗子
在单机版的Springboot+Shiro的基础上,这次实现共享Session. 这里没有自己写RedisManager.SessionDAO.用的 crazycake 写的开源插件 pom.xml ...
- SpringBoot+Shiro入门小栗子
写一个不花里胡哨的纯粹的Springboot+Shiro的入门小栗子 效果如图: 首页:有登录注册 先注册一个,然后登陆 登录,成功自动跳转到home页 home页:通过认证之后才可以进 代码部分: ...
- springboot+shiro+redis(单机redis版)整合教程-续(添加动态角色权限控制)
相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(单机redis版)整合教程 3. springboot+shiro+redis(集群re ...
- Spring Cloud之路:(七)SpringBoot+Shiro实现登录认证和权限管理
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/sage_wang/article/details/79592269一.Shiro介绍1.Shiro是 ...
- springboot+shiro+redis(集群redis版)整合教程
相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(单机redis版)整合教程 3.springboot+shiro+redis(单机red ...
- springboot+shiro+redis(单机redis版)整合教程
相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(集群redis版)整合教程 3.springboot+shiro+redis(单机red ...
随机推荐
- Ubuntu 16.04系统下安装PHP5.6*
Ubuntu 16.04系统默认php7,并没有php5*的包,所以需要自己安装: 方法: 1.删除所有的php包列出安装的php包,dpkg -l | grep php| awk '{print $ ...
- npm安装
淘宝镜像http://npm.taobao.org/ $ npm install -g cnpm --registry=https://registry.npm.taobao.org mac下 sud ...
- Ranking Relevance小结
Ranking Relevance是搜索排序算法的各个影响因子中相当重要的一个部分.对于Ranking Relevance的计算,过去的技术往往分为两个大的方向:Click Behavior和Text ...
- java集合框架(hashSet自定义元素是否相同,重写hashCode和equals方法)
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不一致,元素不可以重复 * (通过哈希值来判断是否是同一个对象) * ----HashSet:底层数据结构是哈希表, * 保证 ...
- Android的root学习
Android的内核就是Linux,所以Android获取root其实和Linux获取root权限是一回事儿.在Linux下获取root权限的时候就是执行sudo或者su,接下来系统会提示输入root ...
- 开发一款直播APP系统软件应该有哪些功能,如何开发?
1.技术实现层面: 技术相对都比较成熟,设备也都支持硬编码.IOS还提供现成的 Video ToolBox框架,可以对摄像头和流媒体数据结构进行处理,但Video ToolBox框架只兼容8.0以上版 ...
- CentOS 7安装Docker
在虚拟机CentOS 7上安装Docker ## 零:检查前提条件: 在Red Hat 和Red Hat系列的Linux发行版中,安装Docker所需的前提提交并不多. ### 1.内 ...
- 蓝桥杯-密码发生器-java
/* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2016, 广州科技贸易职业学院信息工程系学生 * All rights reserved. * 文件名称: ...
- object detection技术演进:RCNN、Fast RCNN、Faster RCNN
object detection我的理解,就是在给定的图片中精确找到物体所在位置,并标注出物体的类别.object detection要解决的问题就是物体在哪里,是什么这整个流程的问题.然而,这个问题 ...
- nginx 高可用
1 nginx负载均衡高可用 1.1 什么是负载均衡高可用 nginx作为负载均衡器,所有请求都到了nginx,可见nginx处于非常重点的位置,如果nginx服务器宕机后端web服务将无法提供服务, ...