Cas之5.2.x版本单点登录自定义REST认证-yellowcong
来源:互联网 发布:淘宝虚拟现实购物 编辑:程序博客网 时间:2024/06/13 00:56
通过接口的方式进行单点登录的操作。REST这种方式是解决验证数据不在CAS服务端,而是在本地端项目源码地址:https://gitee.com/yellowcong/cas_demo/tree/master/cas_rest_demo ,这个破玩意折腾了我3天,才写出来,新累啊,官方文档太坑。
再次强调一下,我是5.2.x版本,jdk 1.8 和tomcat 8.5,源码地址:https://gitee.com/yellowcong/cas_demo/tree/master/cas_rest_demo
架构
https://127.0.0.1:8443/cas
CAS 127.0.0.1:8081 rest-client(认证服务)安装准备
建议先搞好了cas的服务安装,再来完这个
CAS之5.2x版本单点登录服务安装-yellowcong
Cas服务配置
pom.xml
下面的配置很多,但是都是默认的,而且我这个主要的是添加了 rest验证的依赖包
<dependency> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-support-rest-authentication</artifactId> <version>4.2.3.RELEASE</version> <scope>system</scope> <type>jar</type> <optional>true</optional> <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-support-rest-authentication-5.2.0.jar</systemPath> </dependency>
官方文档
pom.xml 完整配置
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apereo.cas</groupId> <artifactId>cas-overlay</artifactId> <packaging>war</packaging> <version>1.0</version> <build> <plugins> <plugin> <groupId>com.rimerosolutions.maven.plugins</groupId> <artifactId>wrapper-maven-plugin</artifactId> <version>0.0.4</version> <configuration> <verifyDownload>true</verifyDownload> <checksumAlgorithm>MD5</checksumAlgorithm> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${springboot.version}</version> <configuration> <mainClass>${mainClassName}</mainClass> <addResources>true</addResources> <executable>${isExecutable}</executable> <layout>WAR</layout> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <warName>cas</warName> <failOnMissingWebXml>false</failOnMissingWebXml> <recompressZippedFiles>false</recompressZippedFiles> <archive> <compress>false</compress> <manifestFile>${manifestFileToUse}</manifestFile> </archive> <overlays> <overlay> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-webapp${app.server}</artifactId> </overlay> </overlays> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> </plugin> </plugins> <finalName>cas</finalName> </build> <dependencies> <dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-webapp${app.server}</artifactId> <version>${cas.version}</version> <type>war</type> <scope>system</scope> <optional>true</optional> <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-webapp-tomcat-5.2.0.war</systemPath> </dependency> <!--引入rest认证相关 start --> <dependency> <groupId>org.jasig.cas</groupId> <artifactId>cas-server-support-rest-authentication</artifactId> <version>4.2.3.RELEASE</version> <scope>system</scope> <type>jar</type> <optional>true</optional> <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/cas-server-support-rest-authentication-5.2.0.jar</systemPath> </dependency> <!--引入rest认证相关 end --> <!-- 权限验证的加密包 --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>4.2.3.RELEASE</version> <scope>system</scope> <type>jar</type> <optional>true</optional> <systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/spring-security-core-4.2.3.RELEASE.jar</systemPath> </dependency> <!-- spring security end --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.3.2</version> </dependency> </dependencies> <properties> <cas.version>5.2.0</cas.version> <springboot.version>1.5.8.RELEASE</springboot.version> <!-- app.server could be -jetty, -undertow, -tomcat, or blank if you plan to provide appserver --> <app.server>-tomcat</app.server> <mainClassName>org.springframework.boot.loader.WarLauncher</mainClassName> <isExecutable>false</isExecutable> <manifestFileToUse>${project.build.directory}/war/work/org.apereo.cas/cas-server-webapp${app.server}/META-INF/MANIFEST.MF</manifestFileToUse> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <repositories> <repository> <id>sonatype-releases</id> <url>http://oss.sonatype.org/content/repositories/releases/</url> <snapshots> <enabled>false</enabled> </snapshots> <releases> <enabled>true</enabled> </releases> </repository> <repository> <id>sonatype-snapshots</id> <url>https://oss.sonatype.org/content/repositories/snapshots/</url> <snapshots> <enabled>true</enabled> </snapshots> <releases> <enabled>false</enabled> </releases> </repository> <repository> <id>shibboleth-releases</id> <url>https://build.shibboleth.net/nexus/content/repositories/releases</url> </repository> </repositories> <profiles> <profile> <activation> <activeByDefault>true</activeByDefault> </activation> <id>exec</id> <properties> <mainClassName>org.apereo.cas.web.CasWebApplication</mainClassName> <isExecutable>true</isExecutable> <manifestFileToUse></manifestFileToUse> </properties> <build> <plugins> <plugin> <groupId>com.soebes.maven.plugins</groupId> <artifactId>echo-maven-plugin</artifactId> <version>0.3.0</version> <executions> <execution> <phase>prepare-package</phase> <goals> <goal>echo</goal> </goals> </execution> </executions> <configuration> <echos> <echo>Executable profile to make the generated CAS web application executable.</echo> </echos> </configuration> </plugin> </plugins> </build> </profile> <profile> <activation> <activeByDefault>false</activeByDefault> </activation> <id>pgp</id> <build> <plugins> <plugin> <groupId>com.github.s4u.plugins</groupId> <artifactId>pgpverify-maven-plugin</artifactId> <version>1.1.0</version> <executions> <execution> <goals> <goal>check</goal> </goals> </execution> </executions> <configuration> <pgpKeyServer>hkp://pool.sks-keyservers.net</pgpKeyServer> <pgpKeysCachePath>${settings.localRepository}/pgpkeys-cache</pgpKeysCachePath> <scope>test</scope> <verifyPomFiles>true</verifyPomFiles> <failNoSignature>false</failNoSignature> </configuration> </plugin> </plugins> </build> </profile> </profiles></project>
application.properties 配置
添加rest验证的服务端
#请求远程调用接口,相当于远程获取数据源#http://127.0.0.1:8081/cas-rest/user/logincas.authn.rest.uri=http://127.0.01:8081/cas-rest/user/login#加密策略cas.authn.rest.passwordEncoder.type=DEFAULTcas.authn.rest.passwordEncoder.characterEncoding=UTF-8#加密算法cas.authn.rest.passwordEncoder.encodingAlgorithm=MD5
官方文档
application.properties完整配置
### CAS Server Context Configuration#server.context-path=/casserver.port=8443#添加认证服务cas.serviceRegistry.initFromJson=true#STEP 4签发证书,如果是用spring boot之类嵌入式的容器,则需要改这里的配置,如果是直接部在tomcat中,则需要把tomcat改成https的#server.ssl.key-store=file:/etc/cas/thekeystore#server.ssl.key-store-password=changeit#server.ssl.key-password=changeit# server.ssl.ciphers=# server.ssl.client-auth=# server.ssl.enabled=# server.ssl.key-alias=# server.ssl.key-store-provider=# server.ssl.key-store-type=# server.ssl.protocol=# server.ssl.trust-store=# server.ssl.trust-store-password=# server.ssl.trust-store-provider=# server.ssl.trust-store-type=#server.max-http-header-size=2097152#server.use-forward-headers=true#server.connection-timeout=20000#server.error.include-stacktrace=ALWAYS#server.compression.enabled=true#server.compression.mime-types=application/javascript,application/json,application/xml,text/html,text/xml,text/plain#server.tomcat.max-http-post-size=2097152#server.tomcat.basedir=build/tomcat#server.tomcat.accesslog.enabled=true#server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)#server.tomcat.accesslog.suffix=.log#server.tomcat.max-threads=10#server.tomcat.port-header=X-Forwarded-Port#server.tomcat.protocol-header=X-Forwarded-Proto#server.tomcat.protocol-header-https-value=https#server.tomcat.remote-ip-header=X-FORWARDED-FOR#server.tomcat.uri-encoding=UTF-8spring.http.encoding.charset=UTF-8spring.http.encoding.enabled=truespring.http.encoding.force=true### CAS Cloud Bus Configuration#spring.cloud.bus.enabled=false# spring.cloud.bus.refresh.enabled=true# spring.cloud.bus.env.enabled=true# spring.cloud.bus.destination=CasCloudBus# spring.cloud.bus.ack.enabled=trueendpoints.enabled=falseendpoints.sensitive=trueendpoints.restart.enabled=falseendpoints.shutdown.enabled=falsemanagement.security.enabled=truemanagement.security.roles=ACTUATOR,ADMINmanagement.security.sessions=if_requiredmanagement.context-path=/statusmanagement.add-application-context-header=falsesecurity.basic.authorize-mode=rolesecurity.basic.enabled=falsesecurity.basic.path=/cas/status/**### CAS Web Application Session Configuration#server.session.timeout=300server.session.cookie.http-only=trueserver.session.tracking-modes=COOKIE### CAS Thymeleaf View Configuration#spring.thymeleaf.encoding=UTF-8spring.thymeleaf.cache=falsespring.thymeleaf.mode=HTML### CAS Log4j Configuration## logging.config=file:/etc/cas/log4j2.xmlserver.context-parameters.isLog4jAutoInitializationDisabled=true### CAS AspectJ Configuration#spring.aop.auto=truespring.aop.proxy-target-class=true### CAS Authentication Credentials##cas.authn.accept.users=casuser::Mellon#REST 认证#请求远程调用接口,相当于远程获取数据源#http://127.0.0.1:8081/cas-rest/user/logincas.authn.rest.uri=http://127.0.01:8081/cas-rest/user/login#加密策略cas.authn.rest.passwordEncoder.type=DEFAULTcas.authn.rest.passwordEncoder.characterEncoding=UTF-8#加密算法cas.authn.rest.passwordEncoder.encodingAlgorithm=MD5
rest证服务
工程目录
Srping+SpringMVC+Mybatis搭建的,数据库是MySQL
CasUser.java
package com.yellowcong.cas.model;import java.util.HashMap;import java.util.Map;import org.codehaus.jackson.annotate.JsonProperty;/** * 创建日期:2017年12月18日 * 创建时间:下午10:44:58 * 创建者 :yellowcong * 机能概要:用于传递给CAS服务器验证数据 */public class CasUser { @JsonProperty("id") private String username; @JsonProperty("@class") // 需要返回实现org.apereo.cas.authentication.principal.Principal的类名接口 private String clazz = "org.apereo.cas.authentication.principal.SimplePrincipal"; @JsonProperty("attributes") private Map<String, Object> attributes = new HashMap<String,Object>(); public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getClazz() { return clazz; } public void setClazz(String clazz) { this.clazz = clazz; } public Map<String, Object> getAttributes() { return attributes; } public void setAttributes(Map<String, Object> attributes) { this.attributes = attributes; }}
官网返回的json数据不正确
UserController.java
package com.yellowcong.controller;import java.io.IOException;import java.io.PrintWriter;import java.io.UnsupportedEncodingException;import javax.servlet.http.HttpServletResponse;import org.codehaus.jackson.map.ObjectMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Scope;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Controller;import org.springframework.util.Base64Utils;import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.RequestHeader;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import com.yellowcong.cas.model.CasUser;import com.yellowcong.model.User;import com.yellowcong.service.UserService;/** * 创建日期:2017年9月23日 <br/> * 创建用户:yellowcong <br/> * 功能描述:用户控制成 */@Controller@RequestMapping("/user")@Scope("prototype")public class UserController { @Autowired private UserService userService; /** * 创建日期:2017年9月23日<br/> * 创建用户:yellowcong<br/> * 功能描述:用户登录操作 * @param username * @param password * @return */ @RequestMapping(value="/login",method=RequestMethod.POST) public void login(@RequestHeader HttpHeaders httpHeaders,HttpServletResponse response){ Object result = null; try { User userWeb = this.obtainUserFormHeader(httpHeaders); //当没有 传递 参数的情况 if(userWeb == null){ result = new ResponseEntity<CasUser>(HttpStatus.NOT_FOUND); } //数据库查找 User dbUser = this.userService.login(userWeb.getUsername()); if (dbUser != null) { if (!dbUser.getPassword().equals(userWeb.getPassword())) { //密码不匹配 result = new ResponseEntity<CasUser>(HttpStatus.BAD_REQUEST); }else if (dbUser.isDisable()) { //禁用 403 result = new ResponseEntity<CasUser>(HttpStatus.FORBIDDEN); }else if (dbUser.isLocked()) { //锁定 423 result = new ResponseEntity<CasUser>(HttpStatus.LOCKED); }else if (dbUser.isExpired()) { //过期 428 result = new ResponseEntity<CasUser>(HttpStatus.PRECONDITION_REQUIRED); }else{ //正常的数据 //直接返回User数据 CasUser casUser = new CasUser(); casUser.setUsername(dbUser.getUsername()); result = casUser; } } else { //不存在 404 result = new ResponseEntity<CasUser>(HttpStatus.NOT_FOUND); } } catch (UnsupportedEncodingException e) { result = new ResponseEntity<CasUser>(HttpStatus.BAD_REQUEST); } //将数据输出到客户端 this.writeJSON(response, result); } /** * 将授权加密的信息返回 * 根据请求头获取用户名及密码 * * @param httpHeaders * @return * @throws UnsupportedEncodingException */ private User obtainUserFormHeader(HttpHeaders httpHeaders) throws UnsupportedEncodingException { /** * * This allows the CAS server to reach to a remote REST endpoint via a POST for verification of credentials. * Credentials are passed via an Authorization header whose value is Basic XYZ where XYZ is a Base64 encoded version of the credentials. */ //根据官方文档,当请求过来时,会通过把用户信息放在请求头authorization中,并且通过Basic认证方式加密 String authorization = httpHeaders.getFirst("authorization");//将得到 Basic Base64(用户名:密码) if(StringUtils.isEmpty(authorization)){ return null; } String baseCredentials = authorization.split(" ")[1]; String usernamePassword = new String(Base64Utils.decodeFromString(baseCredentials), "UTF-8");//用户名:密码 String credentials[] = usernamePassword.split(":"); return new User(credentials[0], credentials[1]); } /** * 在SpringMvc中获取到Session * @return */ @SuppressWarnings("rawtypes") public void writeJSON(HttpServletResponse response,Object object){ try { //设定编码 response.setCharacterEncoding("UTF-8"); //表示是json类型的数据 response.setContentType("application/json"); //获取PrintWriter 往浏览器端写数据 PrintWriter writer = response.getWriter(); //当是不正常的数据的时候,设定状态 if(object instanceof ResponseEntity) { HttpStatus status = ((ResponseEntity) object).getStatusCode(); //设定状态码表 response.setStatus(status.value()); } ObjectMapper mapper = new ObjectMapper(); //转换器 //获取到转化后的JSON 数据 String json = mapper.writeValueAsString(object); //写数据到浏览器 writer.write(json); //刷新,表示全部写完,把缓存数据都刷出去 writer.flush(); //关闭writer writer.close(); } catch (IOException e) { e.printStackTrace(); } }}
接口测试
用户传递过来的时候,
那么请求头authorization=Basic Base64(admin+MD5(123))送后客户端必须响应一下数据,cas明确规定如下:
cas 服务端会通过post请求,并且把用户信息以”用户名:密码”进行Base64编码放在authorization请求头中
返回200状态码并且格式为
{“@class”:”org.apereo.cas.authentication.principal.SimplePrincipal”,”id”:”casuser”,”attributes”:{}}
是成功的; 返回状态码403用户不可用;404账号不存在;423账户被锁定;428过期;其他登录失败
插件使用火狐之RESTClient插件安装-yellowcong
1、配置授权
2、配置请求url
3、发送请求(200的)
json的返回值
4、随便测试一个其他的
测试CAS访问
注意数据库脚本我在后面放着
用户信息
测试登录
正常用户
测试结果
用户禁用
尴尬了,这个用户是禁用的,
数据库脚本
/*SQLyog v10.2 MySQL - 5.1.68-community : Database - yellowcong_cas_rest**********************************************************************//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE=''*/;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;CREATE DATABASE /*!32312 IF NOT EXISTS*/`yellowcong_cas_rest` /*!40100 DEFAULT CHARACTER SET utf8 */;USE `yellowcong_cas_rest`;/*Table structure for table `yellowcong_users` */DROP TABLE IF EXISTS `yellowcong_users`;CREATE TABLE `yellowcong_users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `password` varchar(32) DEFAULT NULL COMMENT '密码', `username` varchar(32) DEFAULT NULL COMMENT '用户名', `is_disable` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否禁用', `is_locked` tinyint(1) DEFAULT '0' COMMENT '是否上锁', `is_expired` tinyint(1) DEFAULT '0' COMMENT '是否过期', PRIMARY KEY (`id`,`is_disable`)) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;/*Data for the table `yellowcong_users` */insert into `yellowcong_users`(`id`,`password`,`username`,`is_disable`,`is_locked`,`is_expired`) values (1,'4748f3d238406505bd50e5accc3a8aa2','yellowcong',0,0,0),(12,'4748f3d238406505bd50e5accc3a8aa2','test',1,0,0),(13,'4748f3d238406505bd50e5accc3a8aa2','test2',0,1,0),(14,'637d1339e213d3ab2777c28e7002df52','doubi',0,0,1);/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
参考文章
https://apereo.github.io/cas/5.1.x/installation/Configuration-Properties.html
https://oss.sonatype.org/content/repositories/releases/org/apereo/cas/
http://blog.csdn.net/u010475041/article/details/77972605
- Cas之5.2.x版本单点登录自定义REST认证-yellowcong
- CAS之5.2x版本单点登录服务安装-yellowcong
- CAS单点登录-自定义认证之Shiro、Rest(六)
- CAS之 5.2x版本配置数据库认证-yellowcong
- CAS之5.2x版本自定义密码验证-yellowcong
- CAS 之3.x版本,单点登录服务搭建(Window)-yellowcong
- Shiro之CAS单点登录-yellowcong
- CAS单点登录-自定义认证之JDBC(五)
- CAS单点登录-自定义认证之重写Credential(十五)
- CAS之3.5版本,单点登录服务搭建(linux)-yellowcong
- CAS之5.2x版本配置密码加密(MD5和SHA)-yellowcong
- 利用CAS之SSO模块实现单点登录认证
- CAS单点登录源码解析之【用户认证】
- 4、CAS单点登录源码解析之【用户认证】
- SSO之CAS+LDAP实现单点登录认证
- sso单点登录,cas统一认证
- jasig CAS实现单点登录(数据库认证)
- jasig CAS实现单点登录(数据库认证)
- 欢迎使用CSDN-markdown编辑器
- 屏蔽kindEditor编辑器编辑图片时自动给图片宽高--解决方案
- android插件自定义之多渠道打包插件(支持微信资源混淆andResGuard)
- 基于Microsoft Visual Studio 2008 的delta3d安装
- php脚本高级分离术
- Cas之5.2.x版本单点登录自定义REST认证-yellowcong
- Sourcetree 使用笔记
- Ubuntu16.04安装maven3.5.2
- 递归专练E 汉诺塔系列之青蛙过河
- Spring中PropertyPlaceholderConfigurer的用法
- 六行代码安装 GPU版本的TensorFlow
- 高度注意 Map 类集合 K/V 能不能存储 null 值的情况
- 在阿里云ECS服务器上搭建tomcat
- php laraval框架 generate 生成key