單點登錄從零開始,搭建cas服務器,集成客戶端springboot,服務器端、客戶端集羣搭建

一、搭建cas服務器
1.下載cas-overlay-template,這裏用的是5.2版本,github地址爲:
https://github.com/apereo/cas-overlay-template/tree/5.2

2.用Intellji Idea打開項目,然後添加當前項目爲maven項目。執行Maven命令mvn install。執行時間較長,需耐心等待。執行結束後,該項目中會出現overlays目錄,裏面就是cas server的配置文件和class代碼。

3.mvn install執行後會在項目的target目錄下生成一個cas.war包,將該war包放在apache tomcat的webapps/目錄下並啓動tomcat後,就能通過瀏覽器訪問,訪問地址 localhost:8080/cas。默認的登錄用戶名和密碼(默認爲casuser/Mellon)

4.重點-修改默認的登錄方式,自定義登錄頁、退出跳轉頁、添加登錄加解密校驗、添加驗證碼等。
4.1 在項目中添加src/main/java和src/main/resources目錄,並將src/main/java設置爲代碼文件根目錄,將src/main/resources設置爲資源文件根目錄。目錄結構如下:
在這裏插入圖片描述
5.在overlay裏面找到casLoginView.html和casLogoutView.html,複製到resource/template目錄下,表單裏面內容及提交方式不變,修改樣式爲我們自定義的樣式,樣式文件可放在自己定義的resource/static目錄下。並在表單中添加驗證碼。
casLoginView:

<!DOCTYPE html>
<!--
  ~ 版權所有.(c)2008-2017.卡爾科技工作室
  -->
<html>
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title th:text="${#themes.code('cas.pageTitle')}"></title>
    <title>登錄</title>
    <link rel="stylesheet"th:href="@{${#themes.code('base.css.file')}}"/>
    <link rel="stylesheet"th:href="@{${#themes.code('login.css.file')}}"/>
    <script th:src="@{${#themes.code('captcha-mini.js.file')}}"></script>
    <script th:src="@{${#themes.code('jquery.min.js.file')}}"></script>
    <script th:src="@{${#themes.code('layer.min.js.file')}}"></script>
    <script th:inline="javascript">
        var ctx = /*[[@{/}]]*/'';
        ctx = ctx.substr(0, ctx.length - 1)
    </script>
</head>

<body class="login_body">
<div class="lgoin_tit">
    <h1>登錄頁</h1>
</div>
<div class="login_main fadeInRight">
    <form method="post" id="fm1" th:object="${credential}" action="login">
        <div class="alert alert-danger" th:if="${#fields.hasErrors('*')}">
            <span th:each="err : ${#fields.errors('*')}" th:utext="${err}"/>
        </div>
        <label class="login_label">
            <span class="login_span_text">賬號:</span>
            <input class="required inp_login" id="username" size="25" tabindex="1" type="text" th:disabled="${guaEnabled}"
                   th:field="*{username}"
                   th:accesskey="#{screen.welcome.label.netid.accesskey}"
                   autocomplete="off"/>
        </label>
        <label class="login_label">
            <span class="login_span_text">密碼:</span>
            <input class="required inp_login" type="password" id="password" size="25" tabindex="2" th:accesskey="#{screen.welcome.label.password.accesskey}" th:field="*{password}"
                   autocomplete="off"/>
        </label>
        <label class="login_label">
            <span class="login_span_text">驗證碼:</span>
            <input class="required inp_login" style="width: 44%"
                   id="capcha"
                   name="capcha"
                   size="25"
                   tabindex="3"
                   th:field="*{capcha}"
                   autocomplete="off" placeholder="請輸入驗證碼"/>
            <span class="login_span_img">
           <img th:src="@{/capcha}" style="width: 160px;height:40px;" id="capchaImg">
        </span>
        </label>
        <a href="javascript:void(0)" onclick="submit()" class="but_login mT20">登錄</a>
        <input type="hidden" name="execution" th:value="${flowExecutionKey}"/>
        <input type="hidden" name="_eventId" value="submit"/>
        <input type="hidden" name="geolocation"/>
        <input class="btn btn-submit btn-block"
               name="submit"
               accesskey="l"
               value="登錄"
               tabindex="6"
               type="submit"
               style="display: none"
               id="login"/>
    </form>
</div>
<script>
    function submit() {

        var username = $("#username").val().trim();
        if (username == null || username == "") {
            layer.tips('請輸入賬號', '#username');
            return;
        }
        var password = $("#password").val().trim();
        if (password == null || password == "") {
            layer.tips('請輸入密碼', '#password');
            return;
        }

        var code = $("#capcha").val().trim();
        if (code == null || code == "") {
            layer.tips('請輸入驗證碼', '#capcha');
            return;
        }
        // 校驗通過後登陸後臺
        $("#login").trigger('click',true);
        // $("#fm1").submit();
    }
</script>
<script type="text/javascript" th:inline="javascript">
    var i = [[#{screen.welcome.button.loginwip}]]
    $("#fm1").submit(function () {
        $(":submit").attr("disabled", true);
        $(":submit").attr("value", i);
        return true;
    });
    $("#capchaImg").click(function () {
        $("#capchaImg").attr("src",ctx+"/capcha");
    })
</script>
</body>
</html>

casLogoutView.html:

<!DOCTYPE html>
<html>
<head>
    <title th:text="#{screen.logout.header}"></title>
    <!-- 以下方式轉到統一身份認證登錄頁面 -->
    <!--    <meta http-equiv="refresh" content="0;url=/cas/login">-->
</head>
<script language="javascript"  type="text/javascript">
    window.onload=function(){//用window的onload事件,窗體加載完畢的時候
        let example = window.location.search;
        console.log(example);
        if(example.indexOf("ebc") != -1){
            window.location.href="";
        }
        else if(example.indexOf("building") != -1){
            window.location.href="";
        }
    }
</script>
</html>

引入的樣式文件:cas-theme-default.properties

standard.custom.css.file=/css/cas.css
admin.custom.css.file=/css/admin.css
cas.javascript.file=/js/cas.js

cas.css.file=/themes/cas/css/cas.css
awesome.css.file=/themes/cas/css/awesome.css
bootstrap.min.css.file=/themes/cas/css/bootstrap.min.css
animate.css.file=/themes/cas/css/animate.css
#login.css.file=/themes/cas/css/login.css
style.css.file=/themes/cas/css/style.css
cas.pageTitle=ARM\u7EDF\u4E00\u8EAB\u4EFD\u8BA4\u8BC1\u5E73\u53F0

base.css.file=/themes/cas/css/base.css
login.css.file=/themes/cas/css/login.css
captcha-mini.js.file=/themes/cas/js/captcha-mini.js
jquery.min.js.file=/themes/cas/js/jquery.min.js
layer.min.js.file=/themes/cas/js/layer/layer.min.js

6.添加自定義接收登錄的參數及驗證碼校驗等
LoginUtil:

package com.jxbd.cas;

import org.apereo.cas.authentication.Credential;
import org.apereo.cas.authentication.HandlerResult;
import org.apereo.cas.authentication.handler.support.AbstractPreAndPostProcessingAuthenticationHandler;
import org.apereo.cas.authentication.PreventedException;
import org.apereo.cas.authentication.principal.PrincipalFactory;
import org.apereo.cas.services.ServicesManager;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.security.auth.login.FailedLoginException;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;

public class LoginUtil extends AbstractPreAndPostProcessingAuthenticationHandler {

    public LoginUtil(String name, ServicesManager servicesManager, PrincipalFactory principalFactory, Integer order) {
        super(name, servicesManager, principalFactory, order);
    }

    @Override
    protected HandlerResult doAuthentication(Credential credential) throws GeneralSecurityException, PreventedException {
        UsernamePasswordCaptchaCredential mycredential1 = (UsernamePasswordCaptchaCredential) credential;

        String capcha = mycredential1.getCapcha().toLowerCase();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String right = attributes.getRequest().getSession().getAttribute("capcha").toString().toLowerCase();
        if(!capcha.equals(right)){
            throw new FailedLoginException("驗證碼錯誤");
        }

        DriverManagerDataSource d = new DriverManagerDataSource();
        d.setDriverClassName("com.mysql.jdbc.Driver");
        d.setUrl("jdbc:mysql://");
        d.setUsername("");
        d.setPassword("");
        JdbcTemplate template = new JdbcTemplate();
        template.setDataSource(d);

        String username=mycredential1.getUsername();
        //查詢數據庫加密的的密碼
        Map<String,Object> user = template.queryForMap("SELECT password FROM sys_user WHERE username = ?", mycredential1.getUsername());
        System.out.println("密碼"+user.get("password"));
        if(user==null){
            throw new FailedLoginException("沒有該用戶");
        }

        //返回多屬性(暫時不知道怎麼用,沒研究)
        Map<String, Object> map=new HashMap<>();
        map.put("email", "[email protected]");

        MyPasswordEncoder encoder = new MyPasswordEncoder();
        if(encoder.matches(mycredential1.getPassword(),user.get("password").toString())){
            return createHandlerResult(mycredential1, principalFactory.createPrincipal(username, map), null);
        }
        throw new FailedLoginException("Sorry, login attemp failed.");
    }

    @Override
    public boolean supports(Credential credential) {
        return credential instanceof UsernamePasswordCaptchaCredential;
    }
}

未完待續。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章