shiro 권한 검증 및 session 공유 실현

12846 단어 Java
1. ShiroRealm 권한 수여/인증
import java.util.List;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.huawei.hicloud.service.UserService;

/**
 *   /  
 * 
 * @author
 *
 */
public class MyShiroRealm extends AuthorizingRealm {

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

	@Autowired
	private UserService userService;

	/**
	 *   
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		logger.info("##### doGetAuthorizationInfo args: " + principalCollection);
		
		//      
		String username = (String) principalCollection.getPrimaryPrincipal();

		//              
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		List roles = userService.getRoles(username);
		simpleAuthorizationInfo.addRoles(roles);
		for (String role : roles) {
			List permissions = userService.getPermissions(role);
			simpleAuthorizationInfo.addStringPermissions(permissions);
		}

		return simpleAuthorizationInfo;
	}

	/**
	 *     
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
			throws AuthenticationException {
		logger.info("##### doGetAuthenticationInfo args: " + authenticationToken);

		UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
		//       
		String userName = token.getUsername();
		char[] password = token.getPassword();
		
		//            ,    ,      
		
		//       
		

		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName, password,
				ByteSource.Util.bytes(userName), getName());

		return authenticationInfo;
	}

}

2. SessionManager
import java.io.Serializable;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.util.StringUtils;

public class MySessionManager extends DefaultWebSessionManager {
	private static final String AUTHORIZATION = "X-Auth-Token";

	private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";

	public MySessionManager() {
		super();
	}

	@Override
	protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
		String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
		//        Authorization    sessionId
		if (!StringUtils.isEmpty(id)) {
			request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
			request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
			request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
			
			return id;
		} else {
			//         cookie sessionId
			return super.getSessionId(request, response);
		}
	}
}

3. Session Dao 재 작성 session 첨삭 개선 실현
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.fastjson.JSON;
import com.huawei.hicloud.components.jedis.JedisClient;

public class RedisSessionDao extends EnterpriseCacheSessionDAO {

	private static final Logger logger = LoggerFactory.getLogger(RedisSessionDao.class);
	
	/** Session    ,  :   */
	private static final Integer SESSION_TIMEOUT = 30*60;

	@Autowired
	private JedisClient jedisClient;

	//   session,      
	@Override
	protected Serializable doCreate(Session session) {
		logger.info("### doCreate session: " + JSON.toJSONString(session));
		Serializable sessionId = super.doCreate(session);
		byte[] key = sessionId.toString().getBytes();
		jedisClient.set(key, sessionToByte(session));
		jedisClient.expire(key, SESSION_TIMEOUT);

		return sessionId;
	}

	//   session
	@Override
	protected Session doReadSession(Serializable sessionId) {
		logger.info("### doReadSession sessionId: {}", sessionId);

		//        session,            
		Session session = super.doReadSession(sessionId);
		if (session == null) {
			byte[] key = sessionId.toString().getBytes();
			byte[] bytes = jedisClient.get(key);
			if (bytes != null && bytes.length > 0) {
				session = byteToSession(bytes);
			}
			jedisClient.expire(key, SESSION_TIMEOUT);
		}
		
		return session;
	}

	//   session         
	@Override
	protected void doUpdate(Session session) {
		logger.info("### doUpdate session: " + JSON.toJSONString(session));
		super.doUpdate(session);
		byte[] key = session.getId().toString().getBytes();
		jedisClient.set(key, sessionToByte(session));
		jedisClient.expire(key, SESSION_TIMEOUT);
	}

	//   session
	@Override
	protected void doDelete(Session session) {
		logger.info("### doDelete session: " + JSON.toJSONString(session));
		super.doDelete(session);
		jedisClient.del(session.getId().toString().getBytes());
	}

	//  session     byte   redis 
	public byte[] sessionToByte(Session session) {
		ByteArrayOutputStream bo = new ByteArrayOutputStream();
		byte[] bytes = null;
		try {
			ObjectOutputStream oo = new ObjectOutputStream(bo);
			oo.writeObject(session);
			bytes = bo.toByteArray();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return bytes;
	}

	//  byte   session
	public Session byteToSession(byte[] bytes) {
		ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
		ObjectInputStream in;
		SimpleSession session = null;
		try {
			in = new ObjectInputStream(bi);
			session = (SimpleSession) in.readObject();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		return session;
	}

}
4. ShiroConfiguration
import java.util.LinkedHashMap;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.huawei.hicloud.components.shiro.MySessionManager;
import com.huawei.hicloud.components.shiro.MyShiroRealm;
import com.huawei.hicloud.components.shiro.RedisSessionDao;

@Configuration
public class ShiroConfiguration {

	/**
	 * Realm  /        
	 * @return
	 */
	@Bean
	public MyShiroRealm myShiroRealm() {
		MyShiroRealm myShiroRealm = new MyShiroRealm();
		
		return myShiroRealm;
	}
	
	/**
	 * Redis  session  
	 * @return
	 */
	@Bean
	public RedisSessionDao redisSessionDao() {
		
		return new RedisSessionDao();
	}

	/**
	 * SessionManager
	 *    SessionDAO  ,  session  
	 * @return
	 */
	@Bean
	public SessionManager sessionManager() {
		MySessionManager mySessionManager = new MySessionManager();
		mySessionManager.setSessionDAO(redisSessionDao());
		mySessionManager.setGlobalSessionTimeout(30 * 60 * 1000);
		
		return mySessionManager;
	}

	/**
	 * SecurityManager
	 *   /  /session/  
	 * @return
	 */
	@Bean
	public SecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(myShiroRealm());
		securityManager.setSessionManager(sessionManager());
		//securityManager.setCacheManager(cacheManager);

		return securityManager;
	}

	/**
	 * Shiro filter  
	 * @param securityManager
	 * @return
	 */
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);

		LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>();
		//   
		filterChainDefinitionMap.put("/logout", "logout");
		//                
		filterChainDefinitionMap.put("/static/**", "anon");
		filterChainDefinitionMap.put("/ajaxLogin", "anon");
		filterChainDefinitionMap.put("/login", "anon");
		//   url    
		filterChainDefinitionMap.put("/**", "authc");

		//   
		shiroFilterFactoryBean.setLoginUrl("/login");
		//   
		shiroFilterFactoryBean.setSuccessUrl("/index");
		//     ,       
		shiroFilterFactoryBean.setUnauthorizedUrl("/error");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

		return shiroFilterFactoryBean;
	}

	/**
	 *   shiro  
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);

		return authorizationAttributeSourceAdvisor;
	}

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

}

5. 로그 인 테스트
Realm 에 가서 인증 을 받 습 니 다.
import java.util.HashMap;
import java.util.Map;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoginController {

	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public Map login(@RequestBody Map params) {
		HashMap result = new HashMap<>();

		Subject subject = SecurityUtils.getSubject();
		UsernamePasswordToken token = new UsernamePasswordToken("shiro", "123456");

		try {
			subject.login(token);
			result.put("token", subject.getSession().getId() + "");
			result.put("msg", "    ");
		} catch (IncorrectCredentialsException e) {
			result.put("msg", "    ");
		} catch (LockedAccountException e) {
			result.put("msg", "    ,       ");
		} catch (AuthenticationException e) {
			result.put("msg", "      ");
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

}

6. 권한 부여 테스트
import java.util.HashMap;
import java.util.Map;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ShiroController {

	@RequiresRoles("admin")
	@RequiresPermissions("rs:view")
	@RequestMapping(value="/shiro", method=RequestMethod.GET)
	public Map shiro() {
		HashMap resultMap = new HashMap<>();
		
		resultMap.put("msg", "Hello shiro!");
		
		return resultMap;
	}
	
}

좋은 웹페이지 즐겨찾기