Spring Boot+Shiro implements Token login and authentication

Because the project needs to be changed to single sign-on, shiro uses the session to verify information, and also retains shiro's authorization verification, so only the verification part needs to be changed to token.

There are many implementations and concepts of Shiro and token on the Internet, so I won’t explain them here.

This article mainly refers to this article https://blog.csdn.net/sqlgao22/article/details/99186391/

Let me talk about the general idea first:

1. After logging in, the token is generated and stored in the database and the token is placed in the cookie. The advantage of this is that the cookie will be automatically taken when the browser sends a request, and there is no need to make any changes to the front end.

2. Each time the front end requests the back end, the token is taken out for verification when verifying.

The focus is on the back-end interception, so we mainly talk about how to do interception.

log in

@PostMapping("login")
	@ApiOperation(value = "登录")
	public Result login(HttpServletRequest request, HttpServletResponse response,@RequestBody LoginDTO login) {

    //用户登录校验代码
    ...
    //shiro验证和授权
    Subject subject = SecurityUtils.getSubject();
    UsernamePasswordToken token = new UsernamePasswordToken(login.getUsername(),                     login.getPassword());
    subject.login(token);
    //createToken方法:生成token,存入cookie并保存到数据库。
    String token1 = sysUserTokenService.createToken(user.getId());
    Cookie cookie = new Cookie("token", token1);
    cookie.setPath("/");
    response.addCookie(cookie);
    //登录成功
    return result;
}

Custom filter blocking

package io.renren.modules.security.token;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.codehaus.groovy.syntax.TokenUtil;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ClientShiroThree extends BasicHttpAuthenticationFilter {
	@Override
	protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse response1) throws Exception {
		HttpServletResponse response = (HttpServletResponse) response1;
		//验证失败直接返回登录页面
		response.sendRedirect("/tlyd/login.html");
		return false;
	}
	@Override
	protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse response, Object mappedValue) {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		String token = "";
		Cookie[] cookies = request.getCookies();
		for (Cookie cookie1 : cookies) {
			if ("token".equals(cookie1.getName())) {
				token=cookie1.getValue();
			}
		}
 		
		if (null == token||"".equals(token)) {
			System.out.println("-------token为空");
			return false;
		}
		//验证token的真实性
		try {
            //校验token并返回用户信息user对象
			User user=TokenUtil.getTokenBody(token);
            
			System.out.println("-------token正确");
            //验证通过重新进行授权
            Subject subject = SecurityUtils.getSubject();
		    UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
		    subject.login(login);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("-------token有问题");
			return false;
		}
		return true;
	}
}

 Perform shiro configuration


package io.renren.modules.security.config;

import io.renren.modules.security.realm.UserRealm;
import io.renren.modules.security.token.ClientShiroThree;
import io.renren.modules.security.token.ShiroSessionManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

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

/**
 * Shiro的配置文件
 *
 * @author Mark [email protected]
 */
@Configuration
public class ShiroConfig {

    /**
     * 单机环境,session交给shiro管理
     */
    @Bean
    @ConditionalOnProperty(prefix = "renren", name = "cluster", havingValue = "false")
    public DefaultWebSessionManager sessionManager(@Value("${renren.globalSessionTimeout:3600}") long globalSessionTimeout){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        sessionManager.setSessionValidationInterval(globalSessionTimeout * 1000);
        sessionManager.setGlobalSessionTimeout(globalSessionTimeout * 1000);

        return sessionManager;
    }


    /**
     * 集群环境,session交给spring-session管理
     */
    @Bean
    @ConditionalOnProperty(prefix = "renren", name = "cluster", havingValue = "true")
    public ServletContainerSessionManager servletContainerSessionManager() {
        return new ServletContainerSessionManager();
    }


    @Bean("securityManager")
        public SecurityManager securityManager(UserRealm userRealmr) {

        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);

        return securityManager;
    }

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        shiroFilter.setLoginUrl("/login.html");
        shiroFilter.setUnauthorizedUrl("/");
        //加入刚刚写的自定义的过滤器ClientShiroThree并给了key:client
        Map<String, Filter> filters = shiroFilter.getFilters();
        filters.put("client", new ClientShiroThree());
        shiroFilter.setFilters(filters);


        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/swagger/**", "anon");
        filterMap.put("/v2/api-docs", "anon");
        filterMap.put("/swagger-ui.html", "anon");
        filterMap.put("/webjars/**", "anon");
        filterMap.put("/swagger-resources/**", "anon");
        filterMap.put("/statics/**", "anon");
        filterMap.put("/login.html", "anon");
        filterMap.put("/login", "anon");
        filterMap.put("/favicon.ico", "anon");
        filterMap.put("/captcha", "anon");
        filterMap.put("/downLoadBrower", "anon");
        filterMap.put("/getBaseOrgSource", "anon");
        filterMap.put("/common/**", "anon");
        filterMap.put("/cadastre/**", "anon");
        //注意这里把上面的client进行配置
        filterMap.put("/**", "client");
        shiroFilter.setFilterChainDefinitionMap(filterMap);

        return shiroFilter;
    }

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

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

}

In this way, the interception can be carried out, you can see the figure below, and get the token from the front end

If you want to inject your server into a custom interceptor, you can’t inject it directly with @Autowired. You can read my article https://blog.csdn.net/qq_36802726/article/details/82841735

 

Guess you like

Origin blog.csdn.net/qq_36802726/article/details/113125134