javascript
shiro session 设置取不到_SpringCloud+shiro+前后端分离
采用json web token的形式解決前后端緩存問題及緩存一致性問題。具體可以看我之前寫的:JSON WEB TOKEN解決跨域、緩存一致性問題 ? 首先簡單介紹下shiro的關鍵概念 Subject:用戶主體(把操作交給SecurityManager) SecurityManager:安全管理器(關聯Realm) Realm: Shiro連接數據的橋梁 配置pom文件:
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version> </dependency>弄一個包專門寫個shiro的配置類,這里新建一個com.hykj.fiserver.env.shiro:
@Configuration public class Config {/*** 常用的過濾器:* anon:無需認證就能訪問 * authc:必須認證了才能訪問 user:必須擁有記住我功能才能訪問 * perms:擁有對每個資源的權限才能訪問* role:擁有某個角色權限才能訪問* @return*/@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean() {ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();bean.setSecurityManager(securityManager());LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();// 添加一個攔截器filterMap.put("/loginAction/login", "anon");//登錄的話無需認證就能訪問filterMap.put("/**", "authc");//攔截所有請求,有認證才能登錄//這里沒有啟用授權過濾器,就是寫個例子//filterMap.put("/user/add", "perms[user:add]");bean.setFilterChainDefinitionMap(filterMap);// 設置登錄請求,這里是被攔截后回轉的頁面bean.setLoginUrl("/loginAction/loginError");// 設置未授權頁面,這里是未授權跳轉的頁面,沒有啟動bean.setUnauthorizedUrl("/loginAction/noauth");return bean;}/*** 安全管理器* @return*/@Beanpublic DefaultWebSecurityManager securityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setSessionManager(sessionManager());securityManager.setRealm(userRealm());return securityManager;}@Beanpublic SessionManager sessionManager() {TokenSessionManager tokenSessionManager = new TokenSessionManager();return tokenSessionManager; }@Beanpublic UserRealm userRealm() {return new UserRealm();} }接下來寫UserRealm public class UserRealm extends AuthorizingRealm {private final static Log _logger = LogFactory.getLog(UserRealm.class);@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//這里是權限認證的地方,我項目中沒有使用shiro的權限認證System.out.println("執行授權");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();// info.addStringPermission("user:add");// 拿到當前登錄的用戶Subject subject = SecurityUtils.getSubject();UserCache currentUser = (UserCache) subject.getPrincipal();info.addStringPermission(currentUser.getOpId());return info;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//subject.login(token);一定會到這里來,這里就是驗證登錄的地方UserCache user = new UserCache();user.setOpId("test");user.setUserPassword("1234");user.setUserName("test");UsernamePasswordToken userToken = (UsernamePasswordToken) token;//這里要判斷用戶名和密碼了,通常是去數據庫核對用戶名和密碼了if(!new String(userToken.getUsername()).equals(user.getUserName())) {//用戶名錯誤throw new UnknownAccountException();}if (!new String(userToken.getPassword()).equals(user.getUserPassword())) {//密碼錯誤throw new IncorrectCredentialsException(); }return new SimpleAuthenticationInfo(user, user.getUserPassword(), "");}}token就是配置在這里了,要求前端在頭中加入token
public class TokenSessionManager extends DefaultWebSessionManager {private static final String TOKEN = "token";private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";private final static Log _logger = LogFactory.getLog(TokenSessionManager.class);public TokenSessionManager() {super();}@Overridepublic Serializable getSessionId(ServletRequest request, ServletResponse response) {// String token = WebUtils.toHttp(request).getHeader(TOKEN);// 前端請求頭必須傳入token的值,把他的值當做是sessionIdif (!StringUtils.isEmpty(token)) {request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, token);request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);_logger.info("token=" + token);return token;} else {_logger.info("token為空");return null;// 否則按默認規則從cookie取sessionId//return super.getSessionId(request, response);}} }接下來進行測試,注意以下幾點: 1.UserRealm做的user 其id為test,密碼為1234,要都匹配才能過 2.登錄失敗是返回/loginAction/loginError,該接口返回一個字符串,如下代碼:
@RequestMapping(value = "/loginError", produces = "application/json; charset=utf-8")@ResponseBodypublic String loginError(@RequestHeader("token") String token) {return "hello world loginError; token = " + token;}3./loginAction/login接口是不會被攔截的,其他請求會被攔截 測試工具:apipost 測試地址1:http://localhost:13001/FIServer/loginAction/userTest
@RequestMapping(value = "/userTest", produces = "application/json; charset=utf-8")@ResponseBodypublic String userTest() {return "hello world Test";}因為不是loginAction/login所以被攔截了,雖然有token但還是被轉發到loginError 測試地址2:http://localhost:13001/FIServer/loginAction/login?username=testname&password=12345
@RequestMapping(value = "/login", produces = "application/json; charset=utf-8")@ResponseBodypublic String login(String username, String password, HttpServletRequest request) {// 獲取當前的用戶Subject subject = SecurityUtils.getSubject();// 封裝用戶的登錄數據UsernamePasswordToken userToken = new UsernamePasswordToken(username, password);try {subject.login(userToken);UserCache user = (UserCache) subject.getPrincipal();System.out.println(user.getOpId());String token = _jwtTokenUtil.createToken(getJSON(user));return "登錄成功token=" + token;} catch (UnknownAccountException e) {return "用戶名錯誤";} catch (IncorrectCredentialsException e) {return "密碼錯誤";}}很明顯因為密碼不是1234所以一定會返回用戶名錯誤
測試地址3:http://localhost:13001/FIServer/loginAction/login?username=test&password=1234
這次就沒有問題啦,注意登錄的時候是沒有token的,并且還會生產token返回給前端,就是圖中看不懂的那一堆字符
總結
以上是生活随笔為你收集整理的shiro session 设置取不到_SpringCloud+shiro+前后端分离的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 香蕉花晒干的功效与作用、禁忌和食用方法
- 下一篇: 荷香茶的功效与作用、禁忌和食用方法