cas5.3.2单点登录-rest认证(十二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34021712/article/details/81544181

原文地址,转载请注明出处: https://blog.csdn.net/qq_34021712/article/details/81544181     ©王赛超 

我们之前在cas服务端整合了shiro,在shirorealm中通过查询数据库获取用户信息和角色等信息,如果都是内部服务,将从数据库中获取信息改为通过调用接口获取信息就可以了,这也是一种方式,这里是演示一下官网的配置。

什么是Rest认证?

cas服务端通过调用其他服务接口,将用户名和密码传过去进行认证。这就是rest认证。

什么情况下需要用到Rest认证?

在不允许cas服务直接访问账号数据库的时候,这个时候就需要用到Rest认证。

具体参考官网

https://apereo.github.io/cas/5.3.x/installation/Rest-Authentication.html

环境介绍

节点 服务名
app1.cas.com:8081 CAS客户端(只是用来测试单点登录用的,代码参考之前博客)
https://server.cas.com:8443/cas CAS服务端
rest.cas.com:8083 rest-client(认证服务)

流程介绍

当用户点击登录后,cas会发送post请求到http://rest.cas.com:8083/login并且把用户信息以"用户名:密码"进行Base64编码放在authorization请求头中。
若输入用户名密码为:admin/123456;那么请求头包括:
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状态码:过期
    ● 其他登录失败

cas服务端配置

pom.xml添加以下依赖,之前的jdbc依赖可以移除了

<dependency>
    <groupId>org.apereo.cas</groupId>
    <artifactId>cas-server-support-rest-authentication</artifactId>
    <version>${cas.version}</version>
</dependency>

application.properties添加如下配置

cas.authn.rest.uri=http://rest.cas.com:8083/login
#如果密码有加密,打开下面配置,我的是明文
#cas.authn.rest.passwordEncoder.type=DEFAULT
#cas.authn.rest.passwordEncoder.characterEncoding=UTF-8
#cas.authn.rest.passwordEncoder.encodingAlgorithm=MD5

rest-client认证服务端配置

rest-client为一个传统的ssm项目,提供一个rest接口,接口遵循上面介绍的规则。这里这展示接口相关代码。

SysUser.java(rest-client响应体)

package com.wangsaichao.cas.dao.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: wangsaichao
 * @date: 2018/8/9
 * @description: cas-rest返回cas服务端信息
 */
public class SysUser {

    @JsonProperty("id")
    @NotNull
    private String username;

    /**
     * 需要返回实现org.apereo.cas.authentication.principal.Principal的类名接口
     */
    @JsonProperty("@class")
    private String clazz = "org.apereo.cas.authentication.principal.SimplePrincipal";


    @JsonProperty("attributes")
    private Map<String, Object> attributes = new HashMap<>();

    @JsonIgnore
    @NotNull
    private String password;

    /**
     * 用户状态,根据状态判断是否可用
     */
    @JsonIgnore
    private String state;

    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;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    @JsonIgnore
    public SysUser addAttribute(String key, Object val) {
        getAttributes().put(key, val);
        return this;
    }
}

UserController.java(验证用户信息的接口)

package com.wangsaichao.cas.controller;

import com.wangsaichao.cas.dao.entity.SysUser;
import com.wangsaichao.cas.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.RestController;

import java.io.UnsupportedEncodingException;

/**
 * @author: wangsaichao
 * @date: 2018/8/1
 * @description: 对比用户信息
 */
@RestController
public class UserController {

    private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserService userService;

    /**
     * 1. cas 服务端会通过post请求,并且把用户信息以"用户名:密码"进行Base64编码放在authorization请求头中
     * 2. 返回200状态码并且格式为{"@class":"org.apereo.cas.authentication.principal.SimplePrincipal","id":"casuser","attributes":{}} 是成功的
     * 2. 返回状态码403用户不可用;404账号不存在;423账户被锁定;428过期;其他登录失败
     * @param httpHeaders
     * @return
     */
    @RequestMapping("/login")
    public Object login(@RequestHeader HttpHeaders httpHeaders){

        logger.info("开始验证服务");

        SysUser user = null;
        try {
            UserTemp userTemp = obtainUserFormHeader(httpHeaders);
            //尝试查找用户库是否存在
            user = userService.selectUser(userTemp.username);
            if (user != null) {
                if (!user.getPassword().equals(userTemp.password)) {
                    //密码不匹配
                    return new ResponseEntity(HttpStatus.BAD_REQUEST);
                }
                if (!"0".equals(user.getState())) {
                    //用户已锁定
                    return new ResponseEntity(HttpStatus.LOCKED);
                }
            } else {
                //不存在 404
                return new ResponseEntity(HttpStatus.NOT_FOUND);
            }
        } catch (UnsupportedEncodingException e) {
            logger.error("用户认证错误", e);
            new ResponseEntity(HttpStatus.BAD_REQUEST);
        }
        //成功返回json
        return user;
    }

    /**
     * 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.
     * @param httpHeaders
     * @return
     * @throws UnsupportedEncodingException
     */
    private UserTemp obtainUserFormHeader(HttpHeaders httpHeaders) throws UnsupportedEncodingException {

        //cas服务端会通过把用户信息放在请求头authorization中,并且通过Basic认证方式加密
        String authorization = httpHeaders.getFirst("authorization");
        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 UserTemp(credentials[0], credentials[1]);
    }

    /**
     * 从请求头中获取用户名和密码
     */
    private class UserTemp {
        private String username;
        private String password;

        public UserTemp(String username, String password) {
            this.username = username;
            this.password = password;
        }
    }



}

测试

先使用admin登录,之后状态改为锁定,再次登录。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_34021712/article/details/81544181