您的位置:首页 > 编程语言 > Java开发

Spring boot + shiro 跨域配置(解决jsessionid丢失问题)

2017-11-08 17:26 1166 查看

后端部分

maven 配置shiro,spring boot就不写了

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.2</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency>


ShiroConfiguration 配置

import com.pamo.mall.util.PropertiesUtil;
import org.apache.shiro.cache.ehcache.EhCacheManager;
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.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfiguration {

private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean){
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();

String[] adminAuths = PropertiesUtil.authRes.getString("admin").split(",");  //加载管理员权限
String[] serviceAuths = PropertiesUtil.authRes.getString("service").split(","); //加载客服权限
String[] anonAuths = PropertiesUtil.authRes.getString("anon").split(",");  //加载游客权限

for(String adminAuth : adminAuths){
filterChainDefinitionMap.put(adminAuth, "authc,roles[admin]");
}
for(String serviceAuth : serviceAuths){
filterChainDefinitionMap.put(serviceAuth, "authc,roles[service]");
}
for(String anonAuth : anonAuths
117b9
){
filterChainDefinitionMap.put(anonAuth, "anon");
}

shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
}

@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
loadShiroFilterChain(shiroFilterFactoryBean);
return shiroFilterFactoryBean;
}

@Bean
public EhCacheManager getEhCacheManager() {
EhCacheManager em = new EhCacheManager();
em.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");  //配置shiro缓存
return em;
}

@Bean(name = "myShiroRealm")
public MyShiroRealm myShiroRealm(EhCacheManager cacheManager) {
MyShiroRealm realm = new MyShiroRealm();
realm.setCacheManager(cacheManager);
return realm;
}

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

@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
daap.setProxyTargetClass(true);
return daap;
}

@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(MyShiroRealm myShiroRealm) {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(myShiroRealm);
dwsm.setCacheManager(getEhCacheManager());
return dwsm;
}

@Bean
public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(securityManager);
return aasa;
}

}


ehcache-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shiroCache">

<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
</ehcache>


资源文件工具类

import java.util.PropertyResourceBundle;

/**
* @comment 资源文件工具类
* @author HE JIA
* @date 2017年7月6日 下午4:32:02
*/
public class PropertiesUtil {

public static PropertyResourceBundle authRes = (PropertyResourceBundle) PropertyResourceBundle.getBundle("props/authority");

}




MyShiroRealm配置

import com.pamo.mall.rest.domain.po.Account;
import com.pamo.mall.rest.service.AccountService;
import org.apache.shiro.authc.*;
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.springframework.beans.factory.annotation.Autowired;

/**
* @Description: realm配置
* @Author: hj
* @Date: 14:19 2017/11/8
*/
public class MyShiroRealm extends AuthorizingRealm {

@Autowired
private AccountService accountService;

/**
* @Description: 授予用户权限
* @Author: hj
* @Date: 14:19 2017/11/8
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String loginName = (String)super.getAvailablePrincipal(principalCollection);
Account account = accountService.findByName(loginName);
if(account != null){
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
if(account.getType() == 1){  //授予账号类型为1的用户具有admin,service的权限
info.addRole("admin");
info.addRole("service");
}
if(account.getType() == 2){  //授予账号类型为2的用户具有service的权限
info.addRole("service");
}
return info;
}
return null;
}

/**
* @Description: 登陆验证
* @Author: hj
* @Date: 14:19 2017/11/8
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token =(UsernamePasswordToken) authenticationToken;

Account user=  accountService.findByName(token.getUsername());
if(user!=null){  //自动校验
return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
}
return null;
}
}


accountService.findByName根据账号获取用户信息就不写了

开始登陆

Controller层

@Autowired
private AccountService accountService;

/**
* 登陆
* @param loginAccount
* @return
*/
@RequestMapping(value = "/login" , method= RequestMethod.POST)
@ResponseBody
public String Login(@RequestBody Account loginAccount){
return accountService.login(loginAccount,getRequest());
}

@RequestMapping(value = "/f",method= RequestMethod.POST)
@ResponseBody
public String test2(@RequestBody Account loginAccount){
return "路过";
}

/**
* 修改密码
* @return
*/
@RequestMapping(value = "/u",method= RequestMethod.POST)
@ResponseBody
public String ModifyPassword(@RequestBody AccountDto accountDto){
return accountService.ModifyPassword(accountDto,getAccount());
}

/**
* @Description: 测试登陆访问
* @Author: hj
* @Date: 9:19 2017/11/8
*/
@RequestMapping(value = "/d",method= RequestMethod.POST)
@ResponseBody
public ResponseMsg test(@RequestBody AccountDto accountDto){
return new ResponseMsg("[客服]登陆成功");
}

/**
* @Description: 测试登陆权限访问
* @Author: hj
* @Date: 9:19 2017/11/8
*/
@RequestMapping(value = "/p",method= RequestMethod.POST)
@ResponseBody
public String test1(@RequestBody AccountDto accountDto){
return "[管理员]登陆成功";
}


Service层

/**
* @Description: 登陆
* @Author: hj
* @Date: 9:38 2017/11/8
*/
public Account login(Account account, HttpServletRequest request) {
UsernamePasswordToken token = new UsernamePasswordToken(account.getUsername(), account.getPassword());
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);  //这一步开始登陆,并跳转到MyShiroRealm类doGetAuthenticationInfo方法中
}catch (UnknownAccountException uae){  //账号错误
throw PExceptionFactory.create("H0003");  //这个是处理错误的方式
}catch(IncorrectCredentialsException ice){  //密码错误
throw PExceptionFactory.create("H0004");
}catch(AuthenticationException ae){  //账号或密码错误
throw PExceptionFactory.create("H0007");
}

Account resultAccount = findByName(account.getUsername());  //根据账号获取用户信息
resultAccount.setSessionId(request.getSession().getId());   //获取本次会话的sessionid

return resultAccount;
}


Account

/**
* @Description: 账户
* @Author: hj
* @Date: 14:43 2017/11/8
*/
public class Account extends SessionIdBean implements Serializable {

private static final long serialVersionUID = 1L;

private Integer id;  //ID

private String username;  //用户名

private String password;  //密码-加密

private Integer type;  //账号类型(1-管理员 2-客服)

@JSONField(format = "YYYY-MM-dd HH:mm:ss")
private Date gmtCreate;  //创建时间

@JSONField(format = "YYYY-MM-dd HH:mm:ss")
private Date gmtUpdate;  //更新时间

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

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

public Integer getType() {
return type;
}

public void setType(Integer type) {
this.type = type;
}

public Date getGmtCreate() {
return gmtCreate;
}

public void setGmtCreate(Date gmtCreate) {
this.gmtCreate = gmtCreate;
}

public Date getGmtUpdate() {
return gmtUpdate;
}

public void setGmtUpdate(Date gmtUpdate) {
this.gmtUpdate = gmtUpdate;
}
}


SessionIdBean

/**
* @Description: SessionId
* @Author: hj
* @Date: 14:41 2017/11/8
*/
public class SessionIdBean implements Serializable{

private String sessionId;

public String getSessionId() {
return sessionId;
}

public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
}


前端部分

想要记住会话状态必须在登陆后记住会话id,之后每次访问都带上这个id,详情如下

<html>
<head>
<meta charset="utf-8">

<title>测试</title>
</head>

<body>

<script type="text/javascript" src="js/jquery-1.8.0.min.js"></script>

<form action="" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" id="username" name="username"/></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" id="password" name="password"/></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="button" id="login" value="登录"/>
<input type="reset" value="重置"/>
</td>
</tr>
</table>
</form>

<input type="button" id="test1" value="不登录可以访问"/>
<input type="button" id="test2" value="客服可以访问"/>
<input type="button" id="test3" value="管理员可以访问"/>

<script type="text/javascript">
var sessionid = "";  //登陆后保存会话id
$("#test3").click(function(){
var settings = {
"xhrFields": "{ withCredentials: true }",
"async": true,
"crossDomain": true,
"url": "http://10.0.0.46:10001/mall-service/account/p;jsessionid="+sessionid,
"type": "POST",
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"processData": false,
"data": "{}"
}

$.ajax(settings).done(function (response) {
console.log(response);
});
});

$("#test2").click(function(){
var settings = {
"xhrFields": "{ withCredentials: true }",
"async": true,
"crossDomain": true,
"url": "http://10.0.0.46:10001/mall-service/account/d;jsessionid="+sessionid,
"type": "POST",
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"processData": false,
"data": "{}"
}

$.ajax(settings).done(function (response) {
console.log(response);
});
});

$("#test1").click(function(){
var settings = {
"xhrFields": "{ withCredentials: true }",
"async": true,
"crossDomain": true,
"url": "http://10.0.0.46:10001/mall-service/account/f;jsessionid="+sessionid,
"type": "POST",
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"processData": false,
"data": "{}"
}

$.ajax(settings).done(function (response) {
console.log(response);
});
});

$("#login").click(function(){
var settings = {
"xhrFields": "{ withCredentials: true }",
"async": true,
"crossDomain": true,
"url": "http://10.0.0.46:10001/mall-service/account/login",
"type": "POST",
"headers": {
"content-type": "application/json",
"cache-control": "no-cache"
},
"processData": false,
"data": "{username:"+$("#username").val()+",password:"+$("#password").val()+"}"
}

$.ajax(settings).done(function (response) {
sessionid = response.result;
console.log(response);
});
});
</script>

</body>
</html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: