上一篇文章简单述说了cas单点登录基于http协议的配置,基本上能够完成单点登录的登录需要,但是在大多数的实际应用情况中,当登录页面统一定制在服务端的时候,返回客户端的信息,往往不单单只有用户基本信息。
例如:在登录过程中,一个用户有多个角色,根据不同的角色定向到不同的页面,或者根据不同角色进行逻辑处理等情况,客户端需要获得用户登录时所选的角色,这样,单单靠配置设置的cas单点登录是没办法完成的,我们需要定制自己的一套返回参数列表来实现。
具体操作如下:
1、创建自己的认证信息类继承UsernamePasswordCredentials,UsernamePasswordCredentials只对用户名和密码进行认证管理,我们定制自己的认证信息类(NbrcCredentials),添加用户角色userRole
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
public class NbrcCredentials extends UsernamePasswordCredentials {
private static final long serialVersionUID = 2053021031579470710L;
private String userRole;
public String getUserRole() {
return userRole;
}
public void setUserRole(String userRole) {
this.userRole = userRole;
}
}
2、修改/src/main/webapp/WEB-INF/login-webflow.xml文件,该文件需修改两处:
1)修改认证信息管理列表类如下:
修改前:
<var name="credentials" class="org.jasig.cas.authentication.principal.UsernamePasswordCredentials" />
修改后:
<var name="credentials" class="nariis.casServer.NbrcCredentials" />
2)添加表单传值的映射如下:viewLoginForm
修改前:
<view-state id="viewLoginForm" view="casLoginView" model="credentials">
<binder>
<binding property="username" />
<binding property="password" />
</binder>
<on-entry>
<set name="viewScope.commandName" value="'credentials'" />
</on-entry>
<transition on="submit" bind="true" validate="true" to="realSubmit">
<evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />
</transition>
</view-state>
修改后:
<view-state id="viewLoginForm" view="casLoginView" model="credentials">
<binder>
<binding property="username" />
<binding property="password" />
<binding property="userRole" /><!-- 添加用户角色 -->
</binder>
<on-entry>
<set name="viewScope.commandName" value="'credentials'" />
</on-entry>
<transition on="submit" bind="true" validate="true" to="realSubmit">
<evaluate expression="authenticationViaFormAction.doBind(flowRequestContext, flowScope.credentials)" />
</transition>
</view-state>
3、修改/src/main/webapp/WEB-INF/deployerConfigContext.xml中的credentialsToPrincipalResolvers
credentialsToPrincipalResolvers主要负责,
一是确认用户要授权,在默认配置中用的DefaultCredentialsToPrincipalResolver来填充角色
二是用这些分解器确认一个服务请求代理票据验证。这个需要明确的是代理登录流程
credentialsToPrincipalResolverslist属性主要是在验证成功之后,将用户属性提取出来。并传递到接入系统中。如果用户数据存储在存在多个数据源中,则在这里可以写多个属性提取器,分别将用户的属性提取出来,然后处理后传递给客户端。
因此,我们需要定制自己的credentialsToPrincipalResolvers解析器,MyCredentialsToPrincipalResolver实现CredentialsToPrincipalResolver,如下:
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.jasig.cas.authentication.principal.Credentials;
import org.jasig.cas.authentication.principal.CredentialsToPrincipalResolver;
import org.jasig.cas.authentication.principal.Principal;
import org.jasig.cas.authentication.principal.SimplePrincipal;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.springframework.jdbc.core.JdbcTemplate;
public class MyCredentialsToPrincipalResolver implements CredentialsToPrincipalResolver {
private JdbcTemplate jdbcTemplate;
private DataSource dataSource;// 查询数据库用
@Override
public Principal resolvePrincipal(Credentials credentials) {
NbrcCredentials up = (NbrcCredentials) credentials;
String name = up.getUsername();
String pwd = up.getPassword();
String sql = "SELECT userid FROM user WHERE user_name = ? "; // 查询id
String id = null;
try {
id = getJdbcTemplate().queryForObject(sql, String.class, name);
if (id != null) {
// 封装其他信息
Map<String, Object> attrs = new HashMap<String, Object>();
attrs.put("username", name);
attrs.put("password", pwd);
attrs.put("userId", id);
attrs.put("userRole", up.getUserRole());
Principal p = new SimplePrincipal(id, attrs);// 封装成包含id的Principal对象
return p;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
public boolean supports(Credentials credentials) {
boolean boo = // 判断是否是用户和密码凭据
UsernamePasswordCredentials.class.isAssignableFrom(credentials
.getClass());
return boo;
}
public final void setDataSource(final DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.dataSource = dataSource;
}
public DataSource getDataSource() {
return dataSource;
}
protected final JdbcTemplate getJdbcTemplate() {
return this.jdbcTemplate;
}
}
逻辑根据自己的业务进行调整,这里只贴出做为参考。
还需修改/src/main/webapp/WEB-INF/deployerConfigContext.xml,如下:
修改前:
<property name="credentialsToPrincipalResolvers">
<list>
<bean
class="org.jasig.cas.authentication.principal.UsernamePasswordCredentialsToPrincipalResolver">
<property name="attributeRepository" ref="attributeRepository" />
</bean>
<bean
class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />
</list>
</property>
修改后:
<property name="credentialsToPrincipalResolvers">
<list>
<bean
class="nariis.casServer.MyCredentialsToPrincipalResolver" >
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean
class="org.jasig.cas.authentication.principal.HttpBasedServiceCredentialsToPrincipalResolver" />
</list>
</property>
服务端的登录页面上还需要添加id为userRole的标签:该部分根据个人需要自己定制
<select id="userRole" name="userRole" οnchange="getRoleIndex();" style="width:175px;height:20px;font-size: 14px; ">
<option value="1">浏览者</option>
<option value="2">管理员</option>
<option value="3">值班人员</option>
</select>
以上配置基本上自定义返回参数已经完成,在客户端取参数的方法如下:
AttributePrincipal principal = (AttributePrincipal) request.getUserPrincipal();
Map<String, Object> attributes = principal.getAttributes();
String password= (String)attributes.get("password");
String username= (String)attributes.get("username");
String userRole= (String)attributes.get("userRole");