單點登錄配置文件
標籤(空格分隔): 單點 配置
公司系統升級,需要搭建一個單點登錄的統一入口,完成後記錄。
1 環境搭建
原始版:
方法一:cas-server-3.5.2 到路徑/modules下下拷貝cas-server-webapp-3.5.2.war這個war包至tomcat的webapps目錄下。爲了登錄方便,我們將cas-server-webapp-3.5.2.war重命名爲cas.war,啓動tomcat以後會自動解壓縮這個war,在webapps目錄下生一個一個cas目錄。在lib中引入對應的數據庫驅動包。
方法二:重新編譯cas-server-webapp 在Lib中加載cas-server-support-jdbc,對應的數據庫驅動包或其他包。
已解壓版:cas服務端放到tomcat下,mysql數據庫Lib中引入mysql驅動,oracle引入oracle驅動
其中webapp 是默認的包 其他是擴展包 加入擴展包時必須加入core包
2 Server端修改
2.1 WEB-INF下
2.1.1 cas.properties
Service.name 可以對應修改 service的url
service.name=http://localhost:8080
Host.name表示當前服務器的名字,在日誌中會顯示,布集羣的話這裏需要修改每個hotsname不能相同
host.name=cas01.example.org
2.1.2 cas-servlet.xml
指定了一些servlet的配置 修改p:followServiceRedirects=true 在退出時會跳到指定的service頁面 (就是鏈接後面跟的)而不是默認的Logout頁面
2.1.3 deployerConfigContext.xml
<!--自己擴展-->
<bean
class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="dataSource"></property>
<property name="sql"
value="select password from tbl_yh where username=?">
</property>
<property name="passwordEncoder"
ref="myPasswordEncoder">
</property>
</bean>
這是數據庫讀取密碼的sql 可以自定義 寫入cas-server-support-jdbc-**.jar包即可
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@ip:port:實例名" />
<property name="username" value="*******" />
<property name="password" value="*******" />
</bean>
這裏配置密碼所在的數據庫 可用mysql/oracle等數據庫 導入相應驅動即可
2.1.4 messages_zh_CN.properties
修改提示語,\classes\messages_zh_CN.properties 可修改提示語等 寫入對應unicode編碼 即可對應顯示 (用戶名或密碼錯誤)
if (!dbPassword.equals(pwd)) {
throw new BadPasswordAuthenticationException();
}
public BadPasswordAuthenticationException()
{
super("error.authentication.credentials.bad.usernameorpassword.password");
}
error.authentication.credentials.bad.usernameorpassword.password=\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef
2.1.5 取消HTTPS
協議:(轉載)
2.1.5.1 打開 cas-server\WEB-INF\deployerConfigContext.xml 文件 ,找到如下配置:
<!-- Required for proxy ticket mechanism. -->
<bean id="proxyAuthenticationHandler"
class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
p:httpClient-ref="httpClient" />
增加參數p:requireSecure=”false”,是否需要安全驗證,即HTTPS,false爲不採用。修改後爲:
<bean id="proxyAuthenticationHandler"
class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"
p:httpClient-ref="httpClient" p:requireSecure="false" />
2.1.5.2打開 cas-server\WEB-INF\spring-configuration\ticketGrantingTicketCookieGenerator.xml ,找到如下配置:
<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
p:cookieSecure="true"
p:cookieMaxAge="-1"
p:cookieName="CASTGC"
p:cookiePath="/cas" />
修改 p:cookieSecure=”true” 爲 p:cookieSecure=”false”
即不開啓https驗證
2.1.5.3打開 cas-server\WEB-INF\spring-configuration\warnCookieGenerator.xml ,找到如下配置:
<bean id="warnCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"
p:cookieSecure="true"
p:cookieMaxAge="-1"
p:cookieName="CASPRIVACY"
p:cookiePath="/cas" />
修改 p:cookieSecure=”true” 爲 p:cookieSecure=”false”
即不開啓https驗證
2.1.6 自定義登錄頁面(轉載)
指定了界面生成 修改其中cas.viewResolver.basename=myview
則所有樣式界面樣式都從WEB-INF/classes/myview.properties 指定的路徑中讀取
參見自定義登錄界面參考
其實CAS所有的界面位置都是在cas.properties(具體位置:cas\WEB-INF\cas.properties)中指定的。我們打開這個文件,找到下面這行
cas.securityContext.status.allowedSubnet=127.0.0.1
cas.themeResolver.defaultThemeName=cas-theme-default
//注意下面這行
cas.viewResolver.basename=default_views
看cas.viewResolver.basename
這個鍵值對,它的值是default_views
,表示的是默認的視圖配置,其實是一個properties文件的名稱而已。大家找找看,在工程中是不是有一個名爲default_views.properties
(具體位置:cas\WEB-INF\classes\default_views.properties )的文件,文件的具體內容如下:
casLoginView.(class)=org.springframework.web.servlet.view.JstlView
casLoginView.url=/WEB-INF/view/jsp/default/ui/casLoginView.jsp
Display login (warning) messages
casLoginMessageView.(class)=org.springframework.web.servlet.view.JstlView
casLoginMessageView.url=/WEB-INF/view/jsp/default/ui/casLoginMessageView.jsp
Login confirmation view (logged in, warn=true)
casLoginConfirmView.(class)=org.springframework.web.servlet.view.JstlView
casLoginConfirmView.url=/WEB-INF/view/jsp/default/ui/casConfirmView.jsp
Logged-in view (logged in, no service provided)
casLoginGenericSuccessView.(class)=org.springframework.web.servlet.view.JstlView
casLoginGenericSuccessView.url=/WEB-INF/view/jsp/default/ui/casGenericSuccess.jsp
Logout view (/logout)
casLogoutView.(class)=org.springframework.web.servlet.view.JstlView
casLogoutView.url=/WEB-INF/view/jsp/default/ui/casLogoutView.jsp
可以看到我們的登錄頁面就是配置在上面的, 裏面還配置了 登錄成功頁面,退出頁面等,這個後面會具體說明。
我們知道了頁面配置後,那麼是不是可以根據業務來具體訂製一套頁面了。
1.在cas.properties 修改 cas.viewResolver.basename 值爲 bokeyuan_view ,那樣系統就會自動會查找 bokeyuan_view.properties 這個配置文件
2.第1點中查找的 bokeyuan_view.properties 是沒有的,我們要自己新建,直接複製原來的 default_views.properties 就行了,重命名爲bokeyuan_view.properties
3.但是bokeyuan_view.properties 中的地址還是 /WEB-INF/view/jsp/default ,我們全部替換把這地址替換成 WEB-INF\view\jsp\bokeyuan
4.接下來我們把 cas\WEB-INF\view\jsp\default 下面的所有文件複製下,然後重命名爲我們需要的名稱,cas\WEB-INF\view\jsp\bokeyuan
5.這樣我們就可以可以隨意修改登錄界面了
ps:有人說直接修改原來的 cas\WEB-INF\view\jsp\default\ui\casLoginView.jsp 就行了,省得麻煩。 其實這樣也是行的,但這樣如果後面需要初始的界面,那樣就沒了。
採用配置修改的方式主要會更加靈活點,可以保留原來的備份。
pps:登錄界面中的jquery庫 是配置在cas\WEB-INF\view\jsp\default\ui\includes\bottom.jsp中的,但是這個是直接引用googleapis 的,我們是不能訪問的,需要修改成你本地或者能夠訪問的CDN庫(百度CDN、360CDN 等)
ppps:你可以隨意修改原來的界面,但是原來的邏輯不能修改,其實主要是 form:form 這標籤裏的東西不要變了。反正你只修改樣式,是肯定不會錯的
2.2 密碼驗證修改
上文deployerConfigContent.xml所做的僅僅是查出用戶名和密碼,一般來說數據庫中不會是明文存儲用戶名密碼的需要做一定的轉碼 所需要在QueryDatabaseAuthenticationHandler
做一定的修改,在cas-server-support-jdbc-3.5.2.1.jar中修改爲
package org.jasig.cas.adaptors.jdbc;
import javax.validation.constraints.NotNull;
import org.jasig.cas.adaptors.utils.Arith;
import org.jasig.cas.adaptors.utils.MD5EncryptUtils;
import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.handler.BadPasswordAuthenticationException;
import org.jasig.cas.authentication.handler.PrincipalNameTransformer;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
public class QueryDatabaseAuthenticationHandler
extends AbstractJdbcUsernamePasswordAuthenticationHandler
{
@NotNull
private String sql;
protected boolean authenticateUsernamePasswordInternal(UsernamePasswordCredentials credentials)
throws AuthenticationException
{
String username = getPrincipalNameTransformer().transform(credentials.getUsername());
String password = credentials.getPassword();
try
{
String dbPassword = (String)getJdbcTemplate().queryForObject(this.sql, String.class, new Object[] { username });
if (dbPassword.equals(你得到的字符串)) {
throw new BadPasswordAuthenticationException();
}
return dbPassword.equals(你得到的字符串);
}
catch (IncorrectResultSizeDataAccessException localIncorrectResultSizeDataAccessException) {}
return false;
}
public void setSql(String sql)
{
this.sql = sql;
}
}
3 Client端修改
3.1 Web.xml部分
3.1.1 完整 web.xml部分
<!-- 用於單點退出,該過濾器用於實現單點登出功能,必須放在listener第一位 -->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!--該過濾器用於實現單點登出功能,必須放在filter第一位-->
<filter>
<filter-name>CASSingleSignOutFilter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CASSingleSignOutFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>casServerLogoutUrl</param-name>
<param-value>http://localhost:8080/cas</param-value>
</context-param>
<!-- 單點登陸退出後跳轉地址 -->
<context-param>
<param-name>jumpindexUrl</param-name>
<param-value>http://localhost:8089</param-value>
</context-param>
<!-- 該過濾器負責用戶的認證工作,必須啓用它 -->
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://localhost:8080/cas</param-value>
<!-- 這裏的server是服務端的IP -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8089</param-value>
</init-param>
<init-param>
<param-name>ignorePattern</param-name>
<param-value>
</param-value>
</init-param>
</filter>
<!-- 該過濾器負責對Ticket的校驗工作,必須啓用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://localhost:8080/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8089</param-value>
</init-param>
<init-param>
<param-name>redirectAfterValidation</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- 該過濾器負責實現HttpServletRequest請求的包裹, 比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登錄用戶的登錄名,可選配置。 -->
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來獲取用戶的登錄名。 比如AssertionHolder.getAssertion().getPrincipal().getName()。 -->
<filter>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3.1.2 Web.xml中認證url修改
<!-- 該過濾器負責用戶的認證工作,必須啓用它 -->
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://localhost:8080/cas</param-value>
<!-- 這裏的server是服務端的IP -->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8089</param-value>
</init-param>
<init-param>
<param-name>ignorePattern</param-name>
<param-value>
</param-value>
</init-param>
</filter>
<!-- 該過濾器負責對Ticket的校驗工作,必須啓用它 -->
<filter>
<filter-name>CAS Validation Filter</filter-name>
<filter-class>
org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://localhost:8080/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://localhost:8089</param-value>
</init-param>
<init-param>
<param-name>redirectAfterValidation</param-name>
<param-value>true</param-value>
</init-param>
</filter>
此處必須要修改 上面爲service地址,下面爲client端地址 ignorePattern爲忽略配置 必須寫在一行裏(這裏是不進入單點驗證的地址:如http://ip:port/redirect.jsp)如果所有地址都要登錄驗證可不寫 例如:
<param-value>/redirect.jsp</param-value>
3.1.3 Web.xml中登出url修改
登錄就在web.xml配置即可,如果帶有單點登錄標識 直接根據用戶名查出密碼等值set到loginvo中模擬登錄,如果沒有正常驗證密碼流程
<context-param>
<param-name>casServerLogoutUrl</param-name>
<param-value>http://localhost:8080/cas</param-value>
</context-param>
<!-- 單點登陸退出後跳轉地址 -->
<context-param>
<param-name>jumpindexUrl</param-name>
<param-value>http://localhost:8089</param-value>
</context-param>
這裏是單點登錄的服務器 配置後 jumpindexUrl
爲client端
3.1.4 其他要注意的事項
單點登出的filter 和listener必須寫在第一個filter和listener 不然會報xml解析異常。單點登錄原理此處不贅述,請自行百度。
3.2登出代碼端修改
3.2.1登出時跳轉方法
退出時引用此處 如http://cas-server-ip:cas-server-port/cas/logout?serivce=http://cas-client-ip:cas-client-port(會轉義)
if("ssologin".equals(res.getMessage())){
HttpServletRequest request = ContextAPI.getReq();
String server = request.getSession().getServletContext()
.getInitParameter("casServerLogoutUrl");
// 客戶端
// 統一身份認證集成手冊
String client = request.getSession().getServletContext().getInitParameter("jumpindexUrl");
if (!"".equals(StringUtils.nullToString(server))) {
server = server.replaceAll("\\\\", "");
server = server + "/logout";
if (!"".equals(StringUtils.nullToString(client))) {
server = server + "?service=" + client + request.getContextPath();
System.out.println("這是單點logout:" + server);
request.getSession().invalidate();
}
}
res.addAttr("logouturl", server);
loginpage = "pages/main/login/ssologout.jsp";
}
3.2.2 ssologout.jsp
<script>function init(){
var res = pc.getInitData();
var logouturl = res.getAttr("logouturl");
window.location.href=logouturl;
};
</script>