《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 http://niocoder.com/2018/03/18/Spring-Security源码分析十六-Spring-Security项目实战/ 「龙飞」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

1. 前言

本章是根据前面Spring Security系列实现一个基于角色的权限管理系统。

1.1 技术栈

  • Spring Boot
  • Spring Security
  • Spring Social(需配置host127.0.0.1 www.merryyou.cn
  • Spring Data JPA
  • Freemarker
  • Mysql
  • Redis
  • 前端miniui(非开源)

1.2 效果图

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_01.png https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_02.png https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_03.png https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_04.png https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_05.png https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_06.png https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_07.png https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_08.png https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_09.png https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_10.png

1.3 部分代码

$.ajax({
url: "${re.contextPath}/connect",
type: "get",
async: true,
dataType: "json",
success: function (data) {
if (data.code === 0) {
if (data.data.qq) {
//解绑
$("#bindingQq").attr("title", "解绑")
$(".fa-qq").addClass("social_title");
} else {
//绑定
$("#bindingQq").attr("title", "绑定")
$(".fa-qq").removeClass("social_title");
}
if (data.data.weixin) {
//解绑
$("#bindingWeixin").attr("title", "解绑")
$(".fa-weixin").addClass("social_title");
} else {
//绑定
$("#bindingWeixin").attr("title", "绑定")
$(".fa-weixin").removeClass("social_title");
}
if (data.data.weibo) {
//解绑
$("#bindingWeibo").attr("title", "解绑")
$(".fa-weibo").addClass("social_title");
} else {
//绑定
$("#bindingWeibo").attr("title", "绑定")
$(".fa-weibo").removeClass("social_title");
}
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(XMLHttpRequest.status);
alert(XMLHttpRequest.readyState);
alert(textStatus); // paser error;
}

});

$.ajax({
url: "${re.contextPath}/role/" + data.id,
cache: false,
success: function (text) {
var o = mini.decode(text);
//设置数的选中状态
console.log(o.menuIds);
var nodes = tree.getAllChildNodes(tree.getRootNode());
for(var i=0;i<nodes.length;i++){
if(o.menuIds.indexOf(nodes[i]['id'])>=0){
tree.checkNode(nodes[i]);
}else{
tree.uncheckNode(nodes[i]);
}
}
form.setData(o);
form.setChanged(false);
}
});

@Override
public List<MenuDto> getMenusList() {
return repository.findAll().stream()
.map(e ->new MenuDto(e.getId(), e.getPId(), e.getName(), e.getUrl()))
.collect(Collectors.toList());
}

@Override
public Set<String> getUrlByname(String username) {
Set<SysMenu> mesnus = new HashSet<>();
userRepository.findByUsername(username)
.getRoles()
.forEach(e->mesnus.addAll(e.getMenus()));
return mesnus.stream().map(e->e.getUrl()).collect(Collectors.toSet());
}

protected void configure(HttpSecurity http) throws Exception {
// http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
http.headers().frameOptions().disable().and()
.formLogin()//使用表单登录,不再使用默认httpBasic方式
.loginPage(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)//如果请求的URL需要认证则跳转的URL
.loginProcessingUrl(SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_FORM)//处理表单中自定义的登录URL
.successHandler(merryyouLoginSuccessHandler)//登录成功处理器,返回JSON
.failureHandler(merryyouAuthenticationfailureHandler)//登录失败处理器
.and()
.apply(validateCodeSecurityConfig)//验证码拦截
.and()
.apply(smsCodeAuthenticationSecurityConfig)
.and()
.apply(merryyouSpringSocialConfigurer)//社交登录
.and()
.rememberMe()
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(securityProperties.getRememberMeSeconds())
.userDetailsService(userDetailsService)
.and()
.sessionManagement()
// .invalidSessionStrategy(invalidSessionStrategy)
.invalidSessionUrl("/session/invalid")
.maximumSessions(securityProperties.getSession().getMaximumSessions())//最大session并发数量1
.maxSessionsPreventsLogin(securityProperties.getSession().isMaxSessionsPreventsLogin())//之后的登录踢掉之前的登录
.expiredSessionStrategy(sessionInformationExpiredStrategy)
.and()
.and()
.logout()
.logoutUrl("/signOut")//默认退出地址/logout
.logoutSuccessUrl("/")//退出之后跳转到注册页面
.deleteCookies("JSESSIONID")
.and()
.authorizeRequests().antMatchers(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_FORM,
SecurityConstants.DEFAULT_REGISTER_URL,
SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_MOBILE,
SecurityConstants.DEFAULT_SIGN_IN_URL_MOBILE_PAGE,
"/register",
"/socialRegister",//社交账号注册和绑定页面
"/user/register",//处理社交注册请求
"/social/info",//获取当前社交用户信息
"/session/invalid",
"/**/*.js",
"/**/*.css",
"/**/*.jpg",
"/**/*.png",
"/**/*.woff2",
"/code/*")
.permitAll()//以上的请求都不需要认证
//.antMatchers("/").access("hasRole('USER')")
.and()
.csrf().disable()//关闭csrd拦截
;
//安全模块单独配置
authorizeConfigProvider.config(http.authorizeRequests());
}

@PreAuthorize("hasAnyAuthority('user:select','user:update')")
@PostMapping(value = "/user/saveUser")
@ResponseBody
public Result saveUser(@RequestParam String data) {
log.info(data);
return sysUserService.save(data);
}

<td style="width:100%;">
<@sec.authorize access="hasAuthority('role:add')">
<a class="mini-button" iconCls="icon-add" onclick="add()">增加</a>
</@sec.authorize>
<@sec.authorize access="hasAuthority('role:update')">
<a class="mini-button" iconCls="icon-add" onclick="edit()">编辑</a>
<@sec.authorize access="hasAuthority('role:del')">
</@sec.authorize>
<a class="mini-button" iconCls="icon-remove" onclick="remove()">删除</a>
</@sec.authorize>
</td>

1.4 启动方式

  1. idea 配置lombok插件,参考lombok-intellij-plugin
  2. 修改application.yml中数据源信息,执行db文件夹下面的sql文件
  3. 修改application-dev.yml 中redis连接信息
  4. 社交登录需配置host文件:127.0.0.1 www.merryyou.cn 微信appid已过期

2. 代码下载

3. 推荐文章

  1. 【译】用Java创建你的第一个区块链-part1
  2. 【译】用Java创建你的第一个区块链-part2:可交易
文章目录
  1. 1. 1. 前言
    1. 1.1. 1.1 技术栈
    2. 1.2. 1.2 效果图
    3. 1.3. 1.3 部分代码
    4. 1.4. 1.4 启动方式
  2. 2. 2. 代码下载
  3. 3. 3. 推荐文章