Springboot+shiro单点登录实现

论坛 期权论坛 脚本     
匿名技术用户   2020-12-21 19:53   52   0

shiro官网:http://shiro.apache.org/

项目结构


单点登录地址配置

biz.properties

biz.ldapUrl=***-ad-01.ymt.corp

springboot加载

Application.java

配置

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class BizConfig {

    @Value("${biz.ldapUrl}")
    private String ldapUrl;
    @Value("${stress.clientIp}")
    private String stressIp;
    @Value("${sit.clientIp}")
    private String sitIp;
    @Value("${uat.clientIp}")
    private String uatIp;
    @Value("${clientport}")
    private String clientPort;

    @Value("${isEnableSend}")
    private boolean isEnableSend;

    @Value("${alarm.cron}")
    private String alarmcron;

    public String getLdapUrl() {
        return ldapUrl;
    }

    public void setLdapUrl(String ldapUrl) {
        this.ldapUrl = ldapUrl;
    }

    public String getStressIp() {
        return stressIp;
    }

    public void setStressIp(String stressIp) {
        this.stressIp = stressIp;
    }

    public String getSitIp() {
        return sitIp;
    }

    public void setSitIp(String sitIp) {
        this.sitIp = sitIp;
    }

    public String getUatIp() {
        return uatIp;
    }

    public void setUatIp(String uatIp) {
        this.uatIp = uatIp;
    }

    public String getClientPort() {
        return clientPort;
    }

    public void setClientPort(String clientPort) {
        this.clientPort = clientPort;
    }

    public boolean isEnableSend() {
        return isEnableSend;
    }

    public void setEnableSend(boolean enableSend) {
        isEnableSend = enableSend;
    }

    public String getAlarmcron() {
        return alarmcron;
    }

    public void setAlarmcron(String alarmcron) {
        this.alarmcron = alarmcron;
    }
}


import com.ymatou.envmanagement.shiro.AdminAuthorizationFilter;
import com.ymatou.envmanagement.shiro.MyAuthorizingRealm;
import com.ymatou.envmanagement.shiro.SecurityFilterChainDefinitionSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;


@Configuration
public class ShiroConfig {

    private static Log logger = LogFactory.getLog(ShiroConfig.class);

    @Bean
    public ShiroFilterFactoryBean shiroFilter() throws Exception {

        Map<String, Filter> filters = new HashMap<String, Filter>();
        filters.put("admin", new AdminAuthorizationFilter());

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();

        shiroFilterFactoryBean.setFilters(filters);
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionSource().getObject());
        return shiroFilterFactoryBean;
    }

    @Bean(name = "securityManager")
    public org.apache.shiro.mgt.SecurityManager securityManager() {

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myRealm());
        return securityManager;
    }

    @Bean
    public AuthorizingRealm myRealm() {
        return new MyAuthorizingRealm();
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public SecurityFilterChainDefinitionSource filterChainDefinitionSource() {
        return new SecurityFilterChainDefinitionSource();
    }

定制代码

import com.ymatou.envmanagement.model.User;
import com.ymatou.envmanagement.util.CurrentUserUtil;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;


public class AdminAuthorizationFilter extends AuthorizationFilter {

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        User user = CurrentUserUtil.getCurrentUser();

        if(user != null){
            return true;
        }

        return false;
    }

}
import com.ymatou.envmanagement.config.BizConfig;
import com.ymatou.envmanagement.exception.BaseRunTimeException;
import com.ymatou.envmanagement.util.LdapHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;


public class MyAuthorizingRealm extends AuthorizingRealm {

    private static Log logger = LogFactory.getLog(MyAuthorizingRealm.class);

    @Autowired
    private BizConfig bizConfig;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken authcToken = (UsernamePasswordToken) token;
        String userName = authcToken.getUsername();
        String password = String.valueOf(authcToken.getPassword());
        logger.info("login userName: " + userName);

        String ldapUrl = bizConfig.getLdapUrl();
        if (LdapHelper.authenticate(userName, password, ldapUrl)) {
            return new SimpleAuthenticationInfo(userName, password, getName());
        } else {
            if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(password)) {
//                password = CipherUtil.encryptMD5(password);
//                User user = userService.getUser(userName, password);
//
//                /**
//                 * 重新放入,防止 shiro报错org.apache.shiro.authc.IncorrectCredentialsException:
//                 * Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - admin, rememberMe=true]
//                 * did not match the expected credentials.
//                 */
//                authcToken.setPassword(password.toCharArray());
//                if(user != null){
//                    return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
//                }else {
//                    throw new BaseRunTimeException("用户名或密码错误");
//                }

                throw new BaseRunTimeException(String.format("Authenticate Failed. UserName: %s", userName));
            }
        }

        return null;
    }
}


import org.apache.shiro.config.Ini;
import org.apache.shiro.web.config.IniFilterChainResolverFactory;
import org.springframework.beans.factory.FactoryBean;


public class SecurityFilterChainDefinitionSource implements FactoryBean<Ini.Section> {
    @Override
    public Ini.Section getObject() throws Exception {
        return loadSection();
    }

    @Override
    public Class<?> getObjectType() {
        return this.getClass();
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    private Ini.Section loadSection() {
        Ini ini = Ini.fromResourcePath("classpath:shiro.ini");
        Ini.Section section = ini.getSection(IniFilterChainResolverFactory.URLS);
        return section;
    }
}

使用示例

import com.ymatou.envmanagement.model.User;
import com.ymatou.envmanagement.util.SessionUtil;
import com.ymatou.envmanagement.util.WapperUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("")
public class LoginController {

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

    @RequestMapping("/auth")
    public Object auth(String username, String password) {

        String errorMessage = "未知错误!";


        if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {

            // 得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
            Subject currentUser = SecurityUtils.getSubject();

            // 如果用户已经登录
            if (currentUser.isAuthenticated()) {
                return WapperUtil.success("该用户已经登录!");
            }

            if(username.equals("admin") && password.equals("admin"))
            {
                // 获取已认证用户User
                User user = new User();
                user.setUsername(username);
                user.setPassword(password);

                // 增加用户的相关数据进入Session
                addUserInfoToSession(user);
                return WapperUtil.success("登录成功");
            }
            // 登录Token验证
            UsernamePasswordToken token = new UsernamePasswordToken(username, password, true);

            try {
                currentUser.login(token);

                // 判断用户是否已经认证
                if (currentUser.isAuthenticated()) {

                    // 获取已认证用户User
                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);

                    // 增加用户的相关数据进入Session
                    addUserInfoToSession(user);
                    return WapperUtil.success("登录成功");
                }
            } catch (AuthenticationException e) { // 登录失败
                errorMessage = e.getCause() != null ? e.getCause().getMessage() : e.getMessage();
                logger.info("登录失败", e);
            } catch (Exception e) {
                errorMessage = "未知错误!";
                logger.info("登录失败", e);
            }
        } else {
            errorMessage = "用户名或密码为空!";
        }

        return WapperUtil.error(errorMessage);
    }


    /**
     * 增加用户的信息到session中
     */
    private void addUserInfoToSession(User user) {

        // 设置用户的信息到session中
        SessionUtil.put(SessionUtil.SESSION_KEY_USER_ID, user.getUsername());
        SessionUtil.put(SessionUtil.SESSION_KEY_USER, user);

    }

    @RequestMapping("/logout")
    public Object logout() {
        Subject subject = SecurityUtils.getSubject();

        if (subject.isAuthenticated()) {
            subject.logout();
            return WapperUtil.success();
        }

        return WapperUtil.error("您还未登录!");
    }

    @RequestMapping("/version")
    public String version() {
        return "2017-03-09-1";
    }

    @RequestMapping("/warmup")
    public String status() {
        return "ok";
    }
}

具体原理参考:http://blog.csdn.net/catoop/article/details/50520958

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP