Single sign on CAS6 - customized user information returned by the server

Keywords: Java JSP xml JDBC

principle

The returned user information is configured in deployerConfigContext.xml

Since you want to customize the returned user information, just inherit org.jasig.services.persondir.support.stubbersonattributedao

1. Create com.jadyer.sso.authentication extensions stubbersonattributedao and copy getPerson() method

Use @ Component(value = "attributeRepository") to define its BeanID

2. Comment < bean in deployerConfigContext.xml Id = "attributerepository" > and < util: Map Id = "attrrepobackingmap" > configuration

3. Modify \ WEB-INF\view\jsp\protocol .0\casServiceValidationSuccess.jsp (do not change the one below 3.0)

For specific changes, see the code posted below

In addition, the information returned to the client is defined by the org.jasig.services.persondir.IPersonAttributeDao interface

Stubbersonattributedao is one of the implementations of IPersonAttributeDao

Other implementations, such as SingleRowJdbcPersonAttributeDao, ldapperpersonattributedao, etc

Therefore, SingleRowJdbcPersonAttributeDao can also be configured in deployerConfigContext.xml

That is, < bean id = "attributerepository" class="org.jasig...persondir.support.jdbc.SingleRowJdbcPersonAttributeDao">

However, I don't think it's very flexible, so I won't post the sample code

Code

Here is the user stubbersonattributedao.java of the user information returned by the custom control

package com.jadyer.sso.authentication;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.jasig.services.persondir.IPersonAttributes;
import org.jasig.services.persondir.support.AttributeNamedPersonImpl;
import org.jasig.services.persondir.support.StubPersonAttributeDao;
import org.springframework.stereotype.Component;
import com.jadyer.sso.model.User;

/**
 * Customized return to client related information
 * Created by Xuanyu < https://jadier.github.io/ > on 2015 / 07 / 18 17:52
 */
@Component(value="attributeRepository")
public class UserStubPersonAttributeDao extends StubPersonAttributeDao {
    @Resource
    private UserDaoJdbc userDaoJdbc;
    @Override
    public IPersonAttributes getPerson(String uid) {
        Map<String, List<Object>> attributes = new HashMap<String, List<Object>>();
        try {
            User user = userDaoJdbc.getByUsername(uid);
            attributes.put("userId", Collections.singletonList((Object)user.getUsercode()));
            attributes.put("username", Collections.singletonList((Object)user.getUsername()));
            attributes.put("usernamePlain", Collections.singletonList((Object)URLEncoder.encode(user.getUsernamePlain(), "UTF-8")));
            attributes.put("blogURL", Collections.singletonList((Object)"https://jadyer.github.io/"));
            attributes.put("blogger", Collections.singletonList((Object)URLEncoder.encode("Xuan Yu", "UTF-8")));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return new AttributeNamedPersonImpl(attributes);
    }
}


Here is the UserDaoJdbc.java used to query the database

package com.jadyer.sso.authentication;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import com.jadyer.sso.model.User;

@Repository
public class UserDaoJdbc {
    private static final String SQL_USER_VERIFY = "SELECT COUNT(*) FROM permission_operator WHERE operator_login=? AND operator_pwd=SHA1(?)";
    private static final String SQL_USER_GET = "SELECT * FROM permission_operator WHERE operator_login=?";
    private JdbcTemplate jdbcTemplate;
    @Resource
    public void setDataSource(DataSource dataSource){
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
    public boolean verifyAccount(String username, String password){
        try{
            //Verify that the user name and password are correct
            return 1==this.jdbcTemplate.queryForObject(SQL_USER_VERIFY, new Object[]{username, password}, Integer.class);
        }catch(EmptyResultDataAccessException e){
            return false;
        }
    }
    public User getByUsername(String username){
        try{
            //Get user information according to user name
            return (User)this.jdbcTemplate.queryForObject(SQL_USER_GET, new Object[]{username}, new UserRowMapper());
        }catch(EmptyResultDataAccessException e){
            return new User();
        }
    }
}

class UserRowMapper implements RowMapper<User> {
    @Override
    public User mapRow(ResultSet rs, int index) throws SQLException {
        User user = new User();
        user.setUsercode(rs.getString("operator_code"));
        user.setUsername(rs.getString("operator_login"));
        user.setUsernamePlain(rs.getString("operator_name"));
        return user;
    }
}

Here is the User.java used

package com.jadyer.sso.model;
public class User {
    private String usercode;
    private String username;
    private String usernamePlain;
    /*-- setter And getter--*/
}

Here is the modified part of deployerConfigContext.xml

<!-- Comment out the default attributeRepository Implementation, using custom UserStubPersonAttributeDao -->
<!--
<bean id="attributeRepository" class="org.jasig.services.persondir.support.StubPersonAttributeDao"
       p:backingMap-ref="attrRepoBackingMap" />

<util:map id="attrRepoBackingMap">
   <entry key="uid" value="uid" />
   <entry key="eduPersonAffiliation" value="eduPersonAffiliation" />
   <entry key="groupMembership" value="groupMembership" />
</util:map>
-->

Here is \ WEB-INF\view\jsp\protocol.0\casServiceValidationSuccess.jsp

<%--

    Licensed to Jasig under one or more contributor license
    agreements. See the NOTICE file distributed with this work
    for additional information regarding copyright ownership.
    Jasig licenses this file to you under the Apache License,
    Version 2.0 (the "License"); you may not use this file
    except in compliance with the License.  You may obtain a
    copy of the License at the following location:

      http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.

--%>
<%@ page session="false" contentType="application/xml; charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
    <cas:authenticationSuccess>
        <cas:user>${fn:escapeXml(assertion.primaryAuthentication.principal.id)}</cas:user>
        <c:if test="${not empty pgtIou}">
                <cas:proxyGrantingTicket>${pgtIou}</cas:proxyGrantingTicket>
        </c:if>
        <c:if test="${fn:length(assertion.chainedAuthentications) > 1}">
          <cas:proxies>
            <c:forEach var="proxy" items="${assertion.chainedAuthentications}" varStatus="loopStatus" begin="0" end="${fn:length(assertion.chainedAuthentications)-2}" step="1">
                 <cas:proxy>${fn:escapeXml(proxy.principal.id)}</cas:proxy>
            </c:forEach>
          </cas:proxies>
        </c:if>
        <!--
        //The new part is as follows: after the validation of CASServer is successful, this page is responsible for generating the XML information that interacts with the client
        //The default casServiceValidationSuccess.jsp only includes the user name and does not provide other property information, so the page needs to be extended
        -->
        <c:if test="${fn:length(assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes) > 0}">
            <cas:attributes>
                <c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">
                    <cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>
                </c:forEach>
            </cas:attributes>
        </c:if>
    </cas:authenticationSuccess>
</cas:serviceResponse>

Finally, the client obtains the index.jsp of the user-defined information returned by the server

<%@ page pageEncoding="UTF-8"%>
<%@ page import="java.util.Map"%>
<%@ page import="java.net.URLDecoder"%>
<%@ page import="org.jasig.cas.client.util.AssertionHolder"%>
<%@ page import="org.jasig.cas.client.authentication.AttributePrincipal"%>

<body style="background-color:#CBE0C9;">
    <span style="color:red; font-size:32px; font-weight:bold;">Client login successful</span>
</body>

<hr size="2">

<%
    AttributePrincipal principal = (AttributePrincipal)request.getUserPrincipal();
    Map<String, Object> attributes = principal.getAttributes();
    out.print("principal.getName()=" + principal.getName() + "<br/>");
    out.print("request.getRemoteUser()=" + request.getRemoteUser() + "<br/>");
    out.print("Login user:" + attributes.get("userId") + "<br/>");
    out.print("Login time:" + AssertionHolder.getAssertion().getAuthenticationDate() + "<br/>");
    out.print("-----------------------------------------------------------------------<br/>");
    for(Map.Entry<String, Object> entry : attributes.entrySet()){
        //When the server returns Chinese, it needs encode. When the client receives and displays Chinese, it needs decode. Otherwise, it will be garbled
        out.print(entry.getKey() + "=" + URLDecoder.decode(entry.getValue().toString(), "UTF-8") + "<br/>");
    }
    out.print("-----------------------------------------------------------------------<br/>");
    Map<String, Object> attributes22 = AssertionHolder.getAssertion().getAttributes();
    for(Map.Entry<String, Object> entry : attributes22.entrySet()){
        out.print(entry.getKey() + "=" + entry.getValue() + "<br/>");
    }
    out.print("-----------------------------------------------------------------------<br/>");
    Map<String, Object> attributes33 = AssertionHolder.getAssertion().getPrincipal().getAttributes();
    for(Map.Entry<String, Object> entry : attributes33.entrySet()){
        out.print(entry.getKey() + "=" + entry.getValue() + "<br/>");
    }
%>

Design sketch

See the next blog in this series for details on how to configure the client (including through spring)

(headache and fever today, client configuration method will be sent tomorrow)

Posted by faifas on Thu, 05 Dec 2019 04:19:41 -0800