SringSecurity安全权限管理手册
SpringSecurity权限管理系统实战—九、数据权限的配置
SpringSecurity权限管理系统实战—九、数据权限的配置⽬录前⾔这⼀章的部分是我写到现在最累的⼀部分,累就累在逻辑的处理上,因为涉及到很多多表的操作,要处理好这部分的逻辑很⿇烦也让我发现了数据库设计之初的⼀些命名问题(之后再解决这个问题)。
就像是⽤户表中的id最好还是⽤user_id,⽽我之前⽤的却是id。
这会导致什么问题呢?⽐如说你在role_user这张关联表中存的肯定是user_id吧,那么你在关联这两个表写sql语句是就要不停的转换id和user_id,脑壳⼦都给你绕晕了。
⾎淋淋的教训,⼤家要注意了。
这篇⽂章只是给⼀个思路,内容和逻辑都太复杂,还要对原有的部分进⾏修改,不能再像之前那样⼀步⼀步贴代码了希望各位⼩伙伴能够多多star⽀持,您的点赞就是我维护的动⼒和中同步更新源码附:⼀、什么是数据权限权限设计具体来说可以分为功能权限和数据权限。
功能权限就是⾓⾊能操作哪些接⼝,⽽数据权限就是⾓⾊能够获取到的哪些数据。
形象点来说,如果现在有⼀个公司,公司上下有很多部门,部门⾥有很多员⼯,⽽数据权限就是为了让某个部门的⼈只能获取到⾃⼰部门或着是指定部门的员⼯信息。
⼆、新建如下表分别是岗位表,部门表,⽤户岗位关联表和⾓⾊部门关联表my_user表中添加dept_id字段。
my_role表中添加data_scpoe字段。
前⼀个很好理解,就是部门的id,后⼀个代表的就是⾓⾊的数据权限范围(这篇⽂章很难写,⽂章所代表的代码内容也很难写,⼤家想要理解透彻还是要从源码⾥看,⾃⼰做⼀遍才能真正的理解)三、效果效果效果就是这样,代码也不贴了,这部分逻辑有点复杂,代码量很⼤,可以⾃⾏去源码中查看。
四、实现这⾥只是介绍下如何实现数据权限,参考了若依项⽬中的实现⽅法⾸先我们⾃定义⼀个注解/*** 数据权限过滤注解* @author codermy* @createTime 2020/8/22*/@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface DataPermission {/*** 部门表的别名*/public String deptAlias() default "";/*** ⽤户表的别名*/public String userAlias() default "";}再定义⼀个切⾯类/*** 数据过滤处理* @author codermy* @createTime 2020/8/22*/@Aspect@Componentpublic class DataScopeAspect {@Autowiredpublic RoleUserService roleUserService;/*** 全部数据权限*/public static final String DATA_SCOPE_ALL = "1";/*** ⾃定数据权限*/public static final String DATA_SCOPE_CUSTOM = "2";/*** 部门数据权限*/public static final String DATA_SCOPE_DEPT = "3";/*** 部门及以下数据权限*/public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";/*** 仅本⼈数据权限*/public static final String DATA_SCOPE_SELF = "5";/*** 数据权限过滤关键字*/public static final String DATA_SCOPE = "dataScope";/*** 配置织⼊点*/@Pointcut("@annotation(com.codermy.myspringsecurityplus.admin.annotation.DataPermission)")public void dataScopePointCut(){}@Before("dataScopePointCut()")public void doBefore(JoinPoint point) throws Throwable{handleDataScope(point);}protected void handleDataScope(final JoinPoint joinPoint){// 获得注解DataPermission controllerDataScope = getAnnotationLog(joinPoint);if (controllerDataScope == null){return;}// 获取当前的⽤户JwtUserDto currentUser = SecurityUtils.getCurrentUser();if (currentUser != null){// 如果是超级管理员,则不过滤数据if (!currentUser.isAdmin()){dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),erAlias());}}}/*** 数据范围过滤** @param joinPoint 切点* @param user ⽤户* @param deptAlias 部门别名* @param userAlias ⽤户别名*/public static void dataScopeFilter(JoinPoint joinPoint, JwtUserDto user, String deptAlias, String userAlias) {StringBuilder sqlString = new StringBuilder();for (MyRole role : user.getRoleInfo()){String dataScope = role.getDataScope();if (DATA_SCOPE_ALL.equals(dataScope)){sqlString = new StringBuilder();break;}else if (DATA_SCOPE_CUSTOM.equals(dataScope)){sqlString.append(StrUtil.format(" OR {}.id IN ( SELECT dept_id FROM my_role_dept WHERE role_id = {} ) ", deptAlias,role.getId()));}else if (DATA_SCOPE_DEPT.equals(dataScope)){sqlString.append(StrUtil.format(" OR {}.id = {} ", deptAlias, user.getMyUser().getDeptId()));}else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)){sqlString.append(StrUtil.format(" OR {}.id IN ( SELECT id FROM my_dept WHERE id = {} or find_in_set( {} , ancestors ) )",deptAlias, user.getMyUser().getDeptId(), user.getMyUser().getDeptId()));}else if (DATA_SCOPE_SELF.equals(dataScope)){if (StrUtil.isNotBlank(userAlias)){sqlString.append(StrUtil.format(" OR {}.id = {} ", userAlias, user.getMyUser().getId()));}else{// 数据权限为仅本⼈且没有userAlias别名不查询任何数据sqlString.append(" OR 1=0 ");}}}if (StrUtil.isNotBlank(sqlString.toString())){BaseEntity baseEntity;for (int i = 0;i < joinPoint.getArgs().length ;i++ ){if (joinPoint.getArgs()[i] instanceof BaseEntity){baseEntity= (BaseEntity) joinPoint.getArgs()[i];baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");}}}}/*** 是否存在注解,如果存在就获取*/private DataPermission getAnnotationLog(JoinPoint joinPoint){Signature signature = joinPoint.getSignature();MethodSignature methodSignature = (MethodSignature) signature;Method method = methodSignature.getMethod();if (method != null){return method.getAnnotation(DataPermission.class);}return null;}}解释⼀下这个切⾯类的作⽤就是:当你在ServiceImpl的某个⽅法上定义了这个注解时,它就会获取当前登录⽤户的⾓⾊的dataScope(就是数据范围),然后⽐较它的值,将相应的sql语句存⼊baseEntity的params中然后我们只需要在对于需要配置数据权限的mapper.xml中添加${params.dataScope}再在调⽤此⽅法的service⽅法上添加注解@DataPermission(deptAlias = "d", userAlias = "u")即可这⾥我在BaseEntity中添加了⼀个params属性来⽤于存放数据权限的sql这样当我们需要调⽤这个sql时,如果未过滤权限时,sql是这样的SELECT u.id, u.dept_id, er_name, u.password, u.nick_name, u.phone, u.email, u.status, u.create_time, u.update_timeFROM my_user uLEFT JOIN my_dept d ON u.dept_id = d.idWHERE u.dept_id = ?OR u.dept_id IN (SELECT e.idFROM my_dept eWHERE FIND_IN_SET(?, ancestors))ORDER BY u.id如果我们给这个⾓⾊的数据权限种类是⾃定数据权限,sql就会是下⾯这样SELECT u.id, u.dept_id, er_name, u.password, u.nick_name, u.phone, u.email, u.status, u.create_time, u.update_timeFROM my_user uLEFT JOIN my_dept d ON u.dept_id = d.idWHERE (u.dept_id = ?OR u.dept_id IN (SELECT e.idFROM my_dept eWHERE FIND_IN_SET(?, ancestors)))AND d.id IN (SELECT dept_idFROM my_role_deptWHERE role_id = 2)ORDER BY u.id那么如果我们给⾓⾊ ‘普通⽤户’如下数据权限那么当我们登录该⾓⾊的⽤户时,便只能访问到相应部门下的⽤户信息。
SSO单点登录Spring-SecurityCAS使用手册
SSO单点登录Spring-SecurityCAS使⽤⼿册1.1概述1.1.1单点登录介绍单点登录(Single Sign On , 简称 SSO )是⽬前⽐较流⾏的服务于企业业务整合的解决⽅案之⼀, SSO 使得在多个应⽤系统中,⽤户只需要登录⼀次就可以访问所有相互信任的应⽤系统。
CAS(Central Authentication Service)是⼀款不错的针对 Web 应⽤的单点登录框架。
本⽂介绍了 CAS 的原理、协议、以及配合Spring-Security在 Tomcat 中的配置和使⽤。
1.1.2 CAS 、Spring Security介绍CAS 是 Yale ⼤学发起的⼀个开源项⽬,旨在为 Web 应⽤系统提供⼀种可靠的单点登录⽅法,CAS 在 2004 年 12 ⽉正式成为 JA-SIG 的⼀个项⽬。
CAS 具有以下特点:开源的企业级单点登录解决⽅案。
CAS Server 为需要独⽴部署的 Web 应⽤。
CAS Client ⽀持⾮常多的客户端(这⾥指单点登录系统中的各个 Web 应⽤),包括 Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。
Spring Security为基于J2EE企业应⽤软件提供了全⾯安全服务。
Spring Security⼴泛⽀持各种⾝份验证模式。
这些验证模型绝⼤多数都由第三⽅提供,或正在开发的有关标准机构提供的,例如Internet Engineering Task Force。
作为补充,Spring Security也提供了⾃⼰的⼀套验证功能。
1.1.3 CAS 原理和协议从结构上看,CAS 包含两个部分: CAS Server 和 CAS Client。
CAS Server 需要独⽴部署,主要负责对⽤户的认证⼯作;CAS Client 负责处理对客户端受保护资源的访问请求,需要登录时,重定向到 CAS Server。
4、Spring Security 安全权限管理手册
Spring Security 3.0 安全权限管理手册参考文献:1、中的spring security权限管理手册。
2、spring security3.0权限管理手册3、spring的相关资料。
本文档内容仅仅作为公司权限管理资料用,对于企业来说,权限管理将是系统中的非常重要的一个模块,权限的设计也是参考相关资料进行整理和补充。
系统将通过数据库进行管理用户权限。
权限管理搭建要的问题:1、区分Authentication(验证)与 Authorization(授权)验证这个用户是谁?用户身份可靠吗?授权某用户A是否可以访问资源R某用户A是否可以执行M操作某用户A是否可以对资源R执行M操作2、SS中的验证特点支持多种验证方式支持多种加密格式支持组件的扩展和替换可以本地化输出信息3、SS中的授权特点支持多种仲裁方式支持组件的扩展和替换支持对页面访问、方法访问、对象访问的授权。
4、SS核心安全实现Web安全通过配置Servlet Filter激活SS中的过滤器链实现Session一致性验证实现免登陆验证(Remember-Me验证)提供一系列标签库进行页面元素的安全控制方法安全通过AOP模式实现安全代理Web安全与方法安全均可以使用表达式语言定义访问规则5、配置SS配置Web.xml,应用安全过滤器配置Spring,验证与授权部分在web页面中获取用户身份在web页面中应用安全标签库实现方法级安全6、配置web.xml7、Spring配置文件中设置命名空间8、通过数据库验证用户身份9、完善web页面验证规则10、自定义验证配置11、本地化消息输出(国际化)根据公司项目的开发要求和集合spring security3.0功能,公司将通过数据库进行对用户身份验证和授权,系统将建立5个基础表进行对权利的管理。
第一部分数据库设计1、表设计create table pub_users(user_id varchar(32),user_account varchar(30),user_name varchar(40),user_password varchar(100),user_desc varchar(100),enabled int,issys int);alter table pub_users add constraint pk_pub_users primary key(user_id);create table pub_authorities(authority_id varchar(32),authority_name varchar(40),authority_desc varchar(100),enabled int,issys int);alter table pub_authorities add constraint pk_pub_authorities primary key(authority_id);create table pub_roles(role_id varchar(32),role_name varchar(40),role_desc varchar(100),enabled int,issys int);alter table pub_roles add constraint pk_pub_roles primary key(role_id);create table pub_resources(resource_id varchar(32),resource_name varchar(100),resource_desc varchar(100),resource_type varchar(40),resource_string varchar(200),priority int,enabled int,issys int);alter table pub_resources add constraint pk_pub_resources primary key(resource_id);create table pub_users_roles(id numeric(12,0) IDENTITY NOT NULL,user_id varchar(32),role_id varchar(32),enabled int);alter table pub_users_roles add constraint pk_pub_users_roles primary key(id); alter table pub_users_roles add constraint fk_users_roles_users foreign key(user_id) references pub_users(user_id);alter table pub_users_roles add constraint fk_users_roles_roles foreign key(role_id) references pub_roles(role_id);create table pub_roles_authorities(id numeric(12,0) IDENTITY NOT NULL,role_id varchar(32),authority_id varchar(32),enabled int);alter table pub_roles_authorities add constraint pk_pub_roles_authorities primary key(id);alter table pub_roles_authorities add constraint fk_pub_roles_authorities_authorities foreign key(authority_id) references pub_authorities(authority_id);alter table pub_roles_authorities add constraint fk_pub_roles_authorities_roles foreign key(role_id) references pub_roles(role_id);create table pub_authorities_resources(id numeric(12,0) IDENTITY NOT NULL,authority_id varchar(32),resource_id varchar(32),enabled int);alter table pub_authorities_resources add constraint pk_pub_authorities_resources primary key(id);alter table pub_authorities_resources add constraint fk_pub_authorities_resources_authorities foreign key(authority_id) references pub_authorities(authority_id);alter table pub_authorities_resources add constraint fk_pub_authorities_resources_resources foreign key(resource_id) references pub_resources(resource_id);3、E-R图如下:第二部分 WEB数据库整合提示:相关代码请参考项目模块1、将数据库表结构和Hibernate建立映射,本系统采用annotation进行对数据库进行零配置处理(请参考hibernate映射),如图。
spring-security权限控制详解
spring-security权限控制详解在本例中,主要讲解spring-boot与spring-security的集成,实现⽅式为:将⽤户、权限、资源(url)采⽤数据库存储⾃定义过滤器,代替原有的 FilterSecurityInterceptor⾃定义实现 UserDetailsService、AccessDecisionManager和InvocationSecurityMetadataSourceService,并在配置⽂件进⾏相应的配置GitHub 地址:⽤户⾓⾊表(基于RBAC权限控制)⽤户表(base_user)code type lengthID varchar32USER_NAME varchar50USER_PASSWORD varchar100NIKE_NAME varchar50STATUS int11⽤户⾓⾊表(base_user_role)code type lengthID varchar32USER_ID varchar32ROLE_ID varchar32⾓⾊表(base_role)code type lengthID varchar32ROLE_CODE varchar32ROLE_NAME varchar64⾓⾊菜单表(base_role_menu)code type lengthID varchar32ROLE_ID varchar32MENU_ID varchar32菜单表(base_menu)code type lengthID varchar32MENU_URL varchar120MENU_SEQ varchar120MENU_PARENT_ID varchar32MENU_NAME varchar50MENU_ICON varchar20MENU_ORDER int11IS_LEAF varchar20实现主要配置类⽤于⽤户表单验证,内部调⽤了authenticationManager完成认证,根据认证结果执⾏successfulAuthentication或者unsuccessfulAuthentication,⽆论成功失败,⼀般的实现都是转发或者重定向等处理。
SpringSecurity怎样使用注解控制权限
SpringSecurity怎样使⽤注解控制权限⼀般的系统在权限设计上,都会分为⾓⾊、权限(RDBC),复杂⼀点的可能会有⽤户组、组织之类的概念。
⽤户的权限是写死的,对应于后台的接⼝或者资源,是没办法改变的,⼀般不对⽤户开放修改权限。
管理员⽤户可以通过给⾓⾊分配权限的⽅式,来实现访问控制。
所以当我们写过滤器,或者⽤⼀些安全框架时(⽐如Shiro,Spring Security),也需要将可变的“⾓⾊”,转化为不可变的“权限”,注⼊到框架中。
具体的可以看我之前写的⼀篇()注⼊当前⽤户的权限后,就需要进⾏访问控制了。
常见的做法有1、路径⽐对之前有个项⽬⽤过⼀次,定义⼀个过滤器,添加到security的过滤链中,在这个过滤器中做这么⼀件事:分析当前访问路径所需要的权限,检查当前⽤户是否具有该权限,做⼀个对⽐,根据对⽐结果来决定当前⽤户是否可以访问该资源。
这种做法的好处是代码的⼊侵性不⾼,不需要再每个接⼝上加注解。
但相对来说,显得不那么直观,可读性⽐较差,所以这次换个⽅法。
2、使⽤注解的⽅式SpringSecurity使⽤注解来控制访问时,需要提前开启这个功能。
在配置类上加上注解@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true)public class SecurityConfig extends WebSecurityConfigurerAdapter {在接⼝中如此使⽤/*** 条件查询*/@PreAuthorize("hasAuthority('IMPORT:SELECT')")@ApiOperation(value = "查询")@GetMapping("/list")public R<Page<Task>> list(TaskDto taskDto){//测试阶段,随机⽣成任务Random random = new Random();//todoint i = random.nextInt(4);if(i == 2) {metroServerAdapterService.reloadShelveTask();}Page<Task> list = taskService.list(taskDto);return R.ok(list);}hasAuthority可以替换成hasRole,虽然可以达到相同的⽬的,但是在使⽤的⽅法上还是有些不同的。
springboot集成springsecurity使用OAUTH2做权限管理的教程
springboot集成springsecurity使⽤OAUTH2做权限管理的教程Spring Security OAuth2主要配置,注意application.yml最后的配置resource filter顺序配置,不然会能获取token但是访问⼀直没有权限WebSecurityConfigurerAdapter 所在服务器的web配置AuthorizationServerConfigurerAdapter 认证服务器配置ResourceServerConfigurerAdapter 资源服务器配置这两个配置在 OAuth2Config.java权限有⼏种模式:“authorization_code”, “client_credentials”, “refresh_token”, “password”, “implicit”,是在请求token时的当grant_type值启动项⽬后:通过controller⽅法上的注解@PreAuthorize,设置权限⾓⾊//获取token,password模式,个⼈ccc的权限,http://localhost:8080/oauth/token?username=ccc&password=456&grant_type=password&scope=test&client_id=client_1&client_secret=123456//check tokenhttp://localhost:8080/oauth/check_token?token=02b2d1ac-2f8d-42b6-8e04-c47ed3601249//access_deniedhttp://localhost:8080/add?access_token=792e1bea-78b8-4a36-bfa8-3b72f1759438//没加token,禁⽌http://127.0.0.1:8080//其他访问需要access_tokenhttp://127.0.0.1:8080?access_token=7357c921-0561-42bd-b02a-2d4a049cf69ehttp://localhost:8080/list?access_token=2a06c35f-0758-48c7-904e-4db5bc7b2b83项⽬结构:Spring Security OAuth2 demo//Controller.javapackage boottest.auth;import org.springframework.security.access.prepost.PreAuthorize;import org.springframework.security.core.Authentication;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.RestController;/*** @author zhanghui* @date 2019/4/24*/@RestController@ResponseBodypublic class Controller {@GetMapping(value = {"/",""})public String defaut(){return "defaut";}@GetMapping("/index")public String index(){return "index";}// direct request to "/logout" for logout@RequestMapping("/login")public String login(){return "<form action=\"/login\" method=\"post\">\n" +" <label for=\"username\">Username</label>:\n" +" <input type=\"text\" id=\"username\" name=\"username\" autofocus=\"autofocus\" /> <br />\n" + " <label for=\"password\">Password</label>:\n" +" <input type=\"password\" id=\"password\" name=\"password\" /> <br />\n" +" <input type=\"submit\" value=\"Login\" />\n" +"</form>";}@GetMapping("/login-error")public String loginerror(){return "login-error";}@PreAuthorize("hasAuthority('ROLE_user')") //判断⾓⾊// @PreAuthorize("hasRole('user')") //同上,判断⾓⾊,会⾃动加前缀 ROLE_@GetMapping("/list")public String list() {//程序内判断roleAuthentication authentication = SecurityContextHolder.getContext().getAuthentication();if(authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_user"))){System.out.println("user role2");}return "to list";}@PreAuthorize("hasAuthority('ROLE_admin')")@GetMapping("/add")public String add() {return "to add";}}//MyUserDetailsService.javapackage boottest.auth;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.AuthorityUtils;import er;import erDetails;import erDetailsService;import ernameNotFoundException;import org.springframework.stereotype.Service;import java.util.List;/*** @author zhanghui* @date 2019/4/24*/@Servicepublic class MyUserDetailsService implements UserDetailsService {/*** 根据⽤户的⾓⾊判断权限*/@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//模拟数据库SysUser sysUser;//password need BCrypt ,/projects/jBCrypt/, BCrypt.javaif("abc".equals(username)){sysUser=new SysUser("abc",BCrypt.hashpw("123", BCrypt.gensalt()),"ROLE_admin,ROLE_user");}else if("ccc".equals(username)){sysUser=new SysUser("ccc",BCrypt.hashpw("456", BCrypt.gensalt()), "ROLE_user");}else {sysUser=null;}if (null == sysUser) {throw new UsernameNotFoundException(username);}// authorities 是 roles 集合List<GrantedAuthority> authorities = maSeparatedStringToAuthorityList(sysUser.getRoles());//上⾯是根据⽤户名查出⽤户信息,下⾯才会⽐较传来的password是否正确return new User(sysUser.getUserName(), sysUser.getPassword(), authorities);}}//OAuth2Config.javapackage boottest.auth;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.http.SessionCreationPolicy;import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;/*** @author zhanghui* @date 2019/4/25*/@Configurationpublic class OAuth2Config {//认证服务器@Configuration@EnableAuthorizationServerclass AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter{@AutowiredAuthenticationManager authenticationManager;@Autowiredprivate MyUserDetailsService myUserDetailsService;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//当grant_type=password 获取token,token的权限是password⼈的⾓⾊权限//当grant_type=client_credentials 获取token, token的权限是下⾯配置的client的权限authoritiesclients.inMemory().withClient("client_1").authorizedGrantTypes("authorization_code", "client_credentials", "refresh_token", "password", "implicit") .authorities("ROLE_user").scopes("test").resourceIds("rId1").secret("123456");}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.tokenStore(new InMemoryTokenStore()).authenticationManager(authenticationManager).userDetailsService(myUserDetailsService);}@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.allowFormAuthenticationForClients().checkTokenAccess("permitAll()"); // for /oauth/check_token}}//资源服务器@Configuration@EnableResourceServerclass ResourceServerConfiguration extends ResourceServerConfigurerAdapter{@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {resources.resourceId("rId1").stateless(false);}@Overridepublic void configure(HttpSecurity http) throws Exception {http// Since we want the protected resources to be accessible in the UI as well we need// session creation to be allowed (it's disabled by default in 2.0.6).sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().authorizeRequests().anyRequest().authenticated();// .and()// .anonymous()// .and()// .authorizeRequests()// .antMatchers("/list").access("#oauth2.hasScope('test') and hasRole('ROLE_user')").antMatchers("/add").access("hasRole('ROLE_admin')");//配置访问控制,必须认证过后才可以访问// .antMatchers("/add").authenticated();//配置访问控制,必须认证过后才可以访问// @formatter:on}}}//SecurityConfig.javapackage boottest.auth;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;/*** @author zhanghui* @date 2019/4/24*/@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true) // 启⽤⽅法级别的权限认证public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailsService myUserDetailsService;@Overrideprotected void configure(HttpSecurity http) throws Exception {// 允许所有⽤户访问"/"和"/index.html"http.requestMatchers().anyRequest().and().authorizeRequests().antMatchers("/oauth/**").permitAll();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {erDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}}//SysUser.javapackage boottest.auth;/*** @author zhanghui* @date 2019/4/24*/public class SysUser {private String userName;private String password;private String roles;public SysUser(String userName, String password, String roles) {erName = userName;this.password = password;this.roles = roles;}public String getUserName() {return userName;}public void setUserName(String userName) {erName = userName;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getRoles() {return roles;}public void setRoles(String roles) {this.roles = roles;}}//application.ymlserver:port: 8080.springframework.web: DEBUG# spring security和oauth2的资源控制互相覆盖,⽆法同时⽣效, 覆盖后,ResourceServer 因缺失配置不能验证token,导致错误,虽然能获取token,但是权限访问失败security:oauth2:resource:filter-order: 3//BCrypt.java// Copyright (c) 2006 Damien Miller <djm@>//// Permission to use, copy, modify, and distribute this software for any// purpose with or without fee is hereby granted, provided that the above// copyright notice and this permission notice appear in all copies.//// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.package boottest.auth;import java.io.UnsupportedEncodingException;import java.security.SecureRandom;/*** BCrypt implements OpenBSD-style Blowfish password hashing using* the scheme described in "A Future-Adaptable Password Scheme" by* Niels Provos and David Mazieres.* <p>* This password hashing system tries to thwart off-line password* cracking using a computationally-intensive hashing algorithm,* based on Bruce Schneier's Blowfish cipher. The work factor of* the algorithm is parameterised, so it can be increased as* computers get faster.* <p>* Usage is really simple. To hash a password for the first time,* call the hashpw method with a random salt, like this:* <p>* <code>* String pw_hash = BCrypt.hashpw(plain_password, BCrypt.gensalt()); <br /> * </code>* <p>* To check whether a plaintext password matches one that has been* hashed previously, use the checkpw method:* <p>* <code>* if (BCrypt.checkpw(candidate_password, stored_hash))<br />* System.out.println("It matches");<br />* else<br />* System.out.println("It does not match");<br /> * </code>* <p>* The gensalt() method takes an optional parameter (log_rounds)* that determines the computational complexity of the hashing:* <p>* <code>* String strong_salt = BCrypt.gensalt(10)<br />* String stronger_salt = BCrypt.gensalt(12)<br />* </code>* <p>* The amount of work increases exponentially (2**log_rounds), so* each increment is twice as much work. The default log_rounds is* 10, and the valid range is 4 to 30.** @author Damien Miller* @version 0.2*/public class BCrypt {// BCrypt parametersprivate static final int GENSALT_DEFAULT_LOG2_ROUNDS = 10;private static final int BCRYPT_SALT_LEN = 16;// Blowfish parametersprivate static final int BLOWFISH_NUM_ROUNDS = 16;// Initial contents of key scheduleprivate static final int P_orig[] = {0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,0x9216d5d9, 0x8979fb1b};private static final int S_orig[] = {0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6};// bcrypt IV: "OrpheanBeholderScryDoubt". The C implementation calls // this "ciphertext", but it is really plaintext or an IV. We keep// the name to make code comparison easier.static private final int bf_crypt_ciphertext[] = {0x4f727068, 0x65616e42, 0x65686f6c,0x64657253, 0x63727944, 0x6f756274};// Table for Base64 encodingstatic private final char base64_code[] = {'.', '/', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J','K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V','W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h','i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't','u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5','6', '7', '8', '9'};// Table for Base64 decodingstatic private final byte index_64[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, 0, 1, 54, 55,56, 57, 58, 59, 60, 61, 62, 63, -1, -1,-1, -1, -1, -1, -1, 2, 3, 4, 5, 6,7, 8, 9, 10, 11, 12, 13, 14, 15, 16,17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,。
Spring 安全管理手册
Spring Security下一页Spring Security安全权限管理手册0.0.2版权 © 2009 Lingo论坛:/bbs/。
Email:xyz20003@。
QQ群:3038490。
2009-05-26 13:41:40序言I. 基础篇1. 一个简单的HelloWorld1.1. 配置过滤器1.2. 使用命名空间1.3. 完善整个项目1.4. 运行示例2. 使用数据库管理用户权限2.1. 修改配置文件2.2. 数据库表结构3. 自定义数据库表结构3.1. 自定义表结构3.2. 初始化数据3.3. 获得自定义用户权限信息3.3.1. 处理用户登陆3.3.2. 检验用户权限4. 自定义登陆页面4.1. 实现自定义登陆页面4.2. 修改配置文件4.3. 登陆页面中的参数配置4.4. 测试一下5. 使用数据库管理资源5.1. 数据库表结构5.2. 初始化数据5.3. 实现从数据库中读取资源信息5.3.1. 需要何种数据格式5.3.2. 替换原有功能的切入点6. 控制用户信息6.1. MD5加密6.2. 盐值加密6.3. 用户信息缓存6.4. 获取当前用户信息II. 保护web篇7. 图解过滤器7.1. HttpSessionContextIntegrationFilter7.2. LogoutFilter7.3. AuthenticationProcessingFilter7.4. DefaultLoginPageGeneratingFilter7.5. BasicProcessingFilter7.6. SecurityContextHolderAwareRequestFilter7.7. RememberMeProcessingFilter7.8. AnonymousProcessingFilter7.9. ExceptionTranslationFilter7.10. SessionFixationProtectionFilter7.11. FilterSecurityInterceptorIII. 保护method篇IV. ACL篇V. 最佳实践篇A. 修改日志B. 常见问题解答C. Spring Security-3.0.0.M1下一页序言序言上一页下一页序言为啥选择Spring Security欢迎阅读咱们写的Spring Security教程,咱们既不想写一个简单的入门教程,也不想翻译已有的国外教程。
springboot学习(七)安全管理springsecurity
springboot学习(七)安全管理springsecuritySpring Security⼊门Spring Security 是 Spring 家族中的⼀个安全管理框架,Spring Boot 对于 Spring Security 提供了⾃动化配置⽅案,可以零配置使⽤ Spring Security添加依赖,只要加⼊依赖,项⽬的所有接⼝都会被⾃动保护起来,访问系统会先需要登录认证<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>默认的⽤户名为user,密码在控制台,每次启动项⽬都会变,对登录的⽤户名/密码进⾏配置,有三种不同的⽅式:1. 在 application.properties 中进⾏配置2. 通过 Java 代码配置在内存中3. 通过 Java 从数据库中加载⽤户名密码配置在 application.properties 中配置=hjyer.password=123456配置完成后,重启项⽬,就可以使⽤这⾥配置的⽤户名/密码登录了在Java代码中配置创建⼀个 Spring Security 的配置类,继承⾃ WebSecurityConfigurerAdapter 类,使⽤BCryptPasswordEncoder 进⾏密码加密(从 Spring5 开始,强制要求密码要加密)@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter {protected void configure(AuthenticationManagerBuilder auth) throws Exception {//配置两个⽤户,密码都加密auth.inMemoryAuthentication() .withUser("hjy1").roles("admin").password("$2a$10$D5GuLLF.OOzP28g9Xy1FKu82dj044JeFsNLpujm8sM7xti4IWCTju").and().withUser("hjy2").roles("user").password("$2a$10$4HMMAfpD0xkwq15ceMY4/OZtlETHvLGhCJox3O1Cn9XmsqAUTLxZq");}@BeanPasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}}Spring Security 中提供了 BCryptPasswordEncoder 密码编码⼯具,可以⾮常⽅便的实现密码的加密加盐,相同明⽂加密出来的结果总是不同,这样就不需要⽤户去额外保存盐的字段了登录配置对于登录接⼝,登录成功后的响应,登录失败后的响应,我们都可以在 WebSecurityConfigurerAdapter 的实现类中进⾏配置@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter{@AutowiredVerifyCodeFilter verifyCodeFilter;@Overrideprotected void configure(HttpSecurity http) throws Exception {http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class);http.authorizeRequests()//开启登录配置.antMatchers("/hello").hasRole("admin")//表⽰访问 /hello 这个接⼝,需要具备 admin 这个⾓⾊.anyRequest().authenticated()//表⽰剩余的其他接⼝,登录之后就能访问.and().formLogin().loginPage("/login_p")//定义登录页⾯,未登录时,访问⼀个需要登录之后才能访问的接⼝,会⾃动跳转到该页⾯.loginProcessingUrl("/doLogin")//登录处理接⼝.usernameParameter("uname")//定义登录时,⽤户名的 key,默认为 username.passwordParameter("passwd")//定义登录时,⽤户密码的 key,默认为 password.successHandler(new AuthenticationSuccessHandler(){//登录成功的处理器@Overridepublic void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication)throws IOException,ServletException{ resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();out.write("success");out.flush();}}).failureHandler(new AuthenticationFailureHandler(){@Overridepublic void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException exception) throws IOException,ServletException{ resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();out.write("fail");out.flush();}}).permitAll()//和表单登录相关的接⼝统统都直接通过.and().logout().logoutUrl("/logout").logoutSuccessHandler(new LogoutSuccessHandler(){@Overridepublic void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication)throws IOException,ServletException{resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();out.write("logout success");out.flush();}}).permitAll().and().httpBasic().and().csrf().disable();}}VerifyCodeFilter是⾃定义的图⽚验证码,可以在 successHandler ⽅法中,配置登录成功的回调,如果是前后端分离开发的话,登录成功后返回 JSON 即可,同理,failureHandler ⽅法中配置登录失败的回调,logoutSuccessHandler 中则配置注销成功的回调忽略拦截如果某⼀个请求地址不需要拦截的话,过滤掉该地址,即该地址不⾛ Spring Security 过滤器链@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter{@Overridepublic void configure(WebSecurity web) throws Exception{web.ignoring().antMatchers("/vercode");}}Spring Security添加验证码验证码⼯具类public class VerifyCode {private int width = 100;// ⽣成验证码图⽚的宽度private int height = 50;// ⽣成验证码图⽚的⾼度private String[] fontNames = {"宋体", "楷体", "⾪书", "微软雅⿊"};private Color bgColor = new Color(255, 255, 255);// 定义验证码图⽚的背景颜⾊为⽩⾊private Random random = new Random();private String codes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";private String text;// 记录随机字符串/*** 获取⼀个随意颜⾊* @return*/private Color randomColor() {int red = random.nextInt(150);int green = random.nextInt(150);int blue = random.nextInt(150);return new Color(red, green, blue);}/*** 获取⼀个随机字体* @return*/private Font randomFont() {String name = fontNames[random.nextInt(fontNames.length)];int style = random.nextInt(4);int size = random.nextInt(5) + 24;return new Font(name, style, size);}/*** 获取⼀个随机字符* @return*/private char randomChar() {return codes.charAt(random.nextInt(codes.length()));}/*** 创建⼀个空⽩的BufferedImage对象* @return*/private BufferedImage createImage() {BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g2 = (Graphics2D) image.getGraphics();g2.setColor(bgColor);// 设置验证码图⽚的背景颜⾊g2.fillRect(0, 0, width, height);return image;}public BufferedImage getImage() {BufferedImage image = createImage();Graphics2D g2 = (Graphics2D) image.getGraphics();StringBuffer sb = new StringBuffer();for(int i = 0; i < 4; i++) {String s = randomChar() + "";sb.append(s);g2.setColor(randomColor());g2.setFont(randomFont());float x = i * width * 1.0f / 4;g2.drawString(s, x, height - 15);}this.text = sb.toString();drawLine(image);return image;}/*** 绘制⼲扰线* @param image*/private void drawLine(BufferedImage image) {Graphics2D g2 = (Graphics2D) image.getGraphics();int num = 5;for(int i = 0; i < num; i++) {int x1 = random.nextInt(width);int y1 = random.nextInt(height);int x2 = random.nextInt(width);int y2 = random.nextInt(height);g2.setColor(randomColor());g2.setStroke(new BasicStroke(1.5f));g2.drawLine(x1, y1, x2, y2);}}public String getText() {return text;}public static void output(BufferedImage image, OutputStream out) throws IOException {ImageIO.write(image, "JPEG", out);}}验证码controller@RestControllerpublic class VerifyController {@GetMapping("/verifyCode")public void code(HttpServletRequest request, HttpServletResponse response) throws IOException {VerifyCode code=new VerifyCode();BufferedImage image=code.getImage();String text=code.getText();HttpSession session=request.getSession();session.setAttribute("index_code",text);VerifyCode.output(image,response.getOutputStream());}}创建了⼀个VerifyCode对象,将⽣成的验证码字符保存到session中,然后通过流将图⽚写到前端,img标签如下<img src="/verifyCode" alt="">⾃定义过滤器@Componentpublic class VerifyCodeFilter extends GenericFilterBean {private String defaultFilterProcessUrl="/doLogin";@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request=(HttpServletRequest)servletRequest;HttpServletResponse response=(HttpServletResponse)servletResponse;if("POST".equalsIgnoreCase(request.getMethod()) && defaultFilterProcessUrl.equals(request.getServletPath())){//验证码验证String requestCaptcha=request.getParameter("code");String genCaptcha=(String)request.getSession().getAttribute("index_code");if(StringUtils.isEmpty(requestCaptcha)){throw new AuthenticationException("验证码不能为空");}if(!genCaptcha.equalsIgnoreCase(requestCaptcha)){throw new AuthenticationException("验证码错误");}filterChain.doFilter(request,response);}}}⾃定义过滤器继承⾃GenericFilterBean,并实现其中的doFilter⽅法,在doFilter⽅法中,当请求⽅法是POST,并且请求地址是/doLogin时,获取参数中的code字段值,该字段保存了⽤户从前端页⾯传来的验证码,然后获取session中保存的验证码,如果⽤户没有传来验证码,则抛出验证码不能为空异常,如果⽤户传⼊了验证码,则判断验证码是否正确,如果不正确则抛出异常,否则执⾏chain.doFilter(request,response);使请求继续向下⾛在WebSecurityConfigurerAdapter 的实现类中进⾏配置,见⼊门登录配置Spring Security登录使⽤json通过分析源码我们发现,默认的⽤户名密码提取在UsernamePasswordAuthenticationFilter过滤器中,如果想将⽤户名密码通过JSON的⽅式进⾏传递,则需要⾃定义相关过滤器将其替换即可⾃定义过滤器:将⽤户名/密码的获取⽅案重新修正下,改为了从JSON中获取⽤户名密码public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {@Overridepublic Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {if(request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE) || request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) {ObjectMapper mapper = new ObjectMapper();UsernamePasswordAuthenticationToken authRequest = null;try(InputStream is = request.getInputStream()) {Map < String, String > authenticationBean = mapper.readValue(is, Map.class);authRequest = new UsernamePasswordAuthenticationToken(authenticationBean.get("username"), authenticationBean.get("password"));} catch(IOException e){ e.printStackTrace();authRequest = new UsernamePasswordAuthenticationToken("", "");} finally{ setDetails(request, authRequest);return this.getAuthenticationManager().authenticate(authRequest);}} else {return super.attemptAuthentication(request, response);}}}在SecurityConfig(WebSecurityConfigurerAdapter 实现类)中,将⾃定义的CustomAuthenticationFilter类加⼊进来即可@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().csrf().disable();http.addFilterAt(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);}@BeanCustomAuthenticationFilter customAuthenticationFilter() throws Exception {CustomAuthenticationFilter filter = new CustomAuthenticationFilter();filter.setAuthenticationSuccessHandler(new AuthenticationSuccessHandler() {@Overridepublic void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();RespBean respBean = RespBean.ok("登录成功!");out.write(new ObjectMapper().writeValueAsString(respBean));out.flush();out.close();}});filter.setAuthenticationFailureHandler(new AuthenticationFailureHandler() {@Overridepublic void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();RespBean respBean = RespBean.error("登录失败!");out.write(new ObjectMapper().writeValueAsString(respBean));out.flush();out.close();}});filter.setAuthenticationManager(authenticationManagerBean());return filter;}SpringSecurity中的⾓⾊继承⾓⾊继承实际上是⼀个很常见的需求,因为⼤部分公司治理可能都是⾦字塔形的,上司可能具备下属的部分甚⾄所有权限,这⼀现实场景,反映到我们的代码中,就是⾓⾊继承了,⾓⾊继承关系的解析在RoleHierarchyImpl类的buildRolesReachableInOneStepMap⽅法中配置⾓⾊的继承关系:@BeanRoleHierarchy roleHierarchy() {RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();String hierarchy = "ROLE_dba > ROLE_admin \n ROLE_admin > ROLE_user";roleHierarchy.setHierarchy(hierarchy);return roleHierarchy;}提供了⼀个RoleHierarchy接⼝的实例,使⽤字符串来描述了⾓⾊之间的继承关系,ROLE_dba具备ROLE_admin的所有权限,⽽ROLE_admin则具备ROLE_user的所有权限,继承与继承之间⽤⼀个换⾏符隔开。
SpringSecurity(二十一):权限管理
SpringSecurity(⼆⼗⼀):权限管理Spring Security提供的功能主要包含两⽅⾯:认证和授权。
Spring Security⽀持多种不同的认证⽅式,但是⽆论开发者采⽤哪种认证⽅式,都不会影响授权功能的使⽤,Spring Security很好的实现了认证和授权两⼤功能的解耦,这也是它受欢迎的原因之⼀认证就是确认⽤户⾝份,也就是我们常说的登录, 授权则是根据系统提前设置好的规则,给⽤户分配可以访问某⼀资源的权限,⽤户根据⾃⼰所具有的权限,去执⾏相应的操作。
从技术上来说,Spring Security提供的权限管理功能主要有两种类型:1.基于过滤器的权限管理2.基于AOP的权限管理基于过滤器的权限管理主要是⽤来拦截HTTP请求,拦截下来之后,根据HTTP请求地址进⾏权限校验。
基于AOP的权限管理则主要是⽤来处理⽅法级别的权限问题,当调⽤某⼀个⽅法是,通过AOP将操作拦截下来,然后判断⽤户是否具备相关的权限,如果具备,则允许⽅法调⽤,否则禁⽌⽅法调⽤。
核⼼概念⾓⾊和权限根据之前的介绍,我们已经知道,在Spring Security⽤户登录成功后,会将当前⽤户登录信息保存在Authentication对象中,Authentication对象有⼀个getAuthorities⽅法⽤来返回当前对象具备的权限信息。
getAuthorities的返回值是Collection<? extends GrantedAuthority>即集合中存放的是GrantedAuthority的⼦类,当需要进⾏权限判断的时候就会调⽤该⽅法获得⽤户的权限。
⽆论⽤户是通过何种⽅式登录的,都是通过这个⽅法获得权限信息。
那么对于Collection<? extends GrantedAuthority>,我们应该理解为是⽤户的⾓⾊还是⽤户的权限呢?从设计层⾯来讲,⾓⾊和权限是两个完全不同的东西,权限是⼀些具体的操作,⽐如读权限,写权限;⾓⾊是某些权限的集合,⽐如管理员⾓⾊(ROLE_ADMIN)从代码层⾯来讲,⾓⾊和权限并没有太⼤的不同,在Spring Security中,⾓⾊和权限的处理⽅式基本是⼀样的,唯⼀的区别在于⾓⾊在⼀些地⽅会⾃动添加⼀个ROLE_前缀,⽽权限不会添加任何前缀⾄于getAuthorities的返回值具体是⾓⾊还是权限,取决于我们权限系统的设计。
集成spring security3.0权限控制
集成spring security3.0权限控制收藏最近在一个项目中使用权限控制,由于之前使用的是spring acegi感觉还不错挺好用但这个版本比较老了,所以就研究了一下最新版本的spring security3.0,目前3.0的网上的相关文档及其至少(官方中的3.0文档资料有很多都是spring security2.*的),遂把自己的这几天研究的成果拿出来与大家分享。
希望对大家有所帮助!首先现在数据库中创建一些数据库脚本(本例数据库采用的是Oracle,需根据个人所使用的数据库进行更改相应的数据类型):CREATE TABLE resources (id int NOT NULL primary key,type varchar2(255),value varchar2(255)) ;insert into resources(id,type,value) values (1,'URL','/**');CREATE TABLE role (id int NOT NULL,name varchar2(255),description varchar2(255),PRIMARY KEY (id));insert into role(id,name,description) values(1,'ROLE_USER','ROLE_USER'),(2,'ROLE_ADMIN','ROLE_ADMIN');CREATE TABLE role_resources (role_idint NOT NULL,resource_idint NOT NULL,PRIMARY KEY (role_id,resource_id),CONSTRAINT FKAEE599B751827FA1 FOREIGN KEY (role_id) REFERENCES role (id),CONSTRAINT FKAEE599B7EFD18D21 FOREIGN KEY (resource_id) REFERENCES resources (id)) ;insert intorole_resources(role_id,resource_id) values (1,1),(2,1);CREATE TABLE users (id int NOT NULL PRIMARY KEY ,name varchar2(255) default NULL,password varchar2(255) default NULL,disabled int NOT NULL);insert into users(id,name,password,disabled) values(1,'fzt','21232f297a57a5a743894a0e4a801fc3',0),(2,'Victor','21232f297a57a5 a743894a0e4a801fc3',0);CREATE TABLE user_role (user_idint NOT NULL,role_idint NOT NULL,PRIMARY KEY (user_id,role_id),CONSTRAINT FK143BF46A51827FA1 FOREIGN KEY (role_id) REFERENCES role (id),CONSTRAINT FK143BF46AF6AD4381 FOREIGN KEY (user_id) REFERENCES users (id));insert into user_role(user_id,role_id) values (1,1),(1,2),(2,1);注:用户表中的密码为admin以下是model类模型:User.javapackagecom.xindun.axt.model;importjava.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set;import javax.persistence.Entity;import javax.persistence.FetchType;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.JoinTable;import javax.persistence.ManyToMany;import javax.persistence.SequenceGenerator;import javax.persistence.Table;import javax.persistence.Transient;ng.StringUtils;import org.hibernate.annotations.Cache;import org.hibernate.annotations.CacheConcurrencyStrategy;import org.hibernate.annotations.Proxy;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.GrantedAuthorityImpl; erDetails;/*** <p>Title: an User.java file of the portal project. </p>* <p>Description: 获取用户信息</p>* <p>Create Time: 2009-11-6 下午02:10:34 </p>* <p>Company: ×× Network Tech Co., Ltd</p>* @author Victor Von* @version 1.0*/@Entity@Proxy(lazy = false)@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)@Table(uniqueConstraints={}, name="users")public class User implements UserDetails {private static final long serialVersionUID = 8026813053768023527L;@SequenceGenerator(name="SEQ_USER",sequenceName="seq_user",alloca tionSize=1)@Id@GeneratedValue(strategy =GenerationType.SEQUENCE,generator="SEQ_USER")private Integer id;private String name;private String password;/** 是否正常使用0为已禁止1为正常使用*/private int disabled;@ManyToMany(targetEntity = Role.class, fetch = FetchType.EAGER) @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)private Set<Role> roles;@Transientprivate Map<String, List<Resource>>roleResources;/*** The default constructor*/public User() {}/* (non-Javadoc)* @seeerDetails#getAuthorities()*/public Collection<GrantedAuthority>getAuthorities() {Collection<GrantedAuthority>grantedAuthorities = newArrayList<GrantedAuthority>(roles.size());for(Role role : roles) {grantedAuthorities.add(new GrantedAuthorityImpl(role.getName()));}return grantedAuthorities;}/*** Returns the authorites string** eg.* downpour --- ROLE_ADMIN,ROLE_USER* robbin --- ROLE_ADMIN** @return*/public String getAuthoritiesString() {List<String> authorities = new ArrayList<String>();for(GrantedAuthority authority : this.getAuthorities()) {authorities.add(authority.getAuthority());}return StringUtils.join(authorities, ",");}/* (non-Javadoc)* @see erDetails#getPassword() */public String getPassword() {return password;}/* (non-Javadoc)* @see erDetails#getUsername() */public String getUsername() {return name;}/* (non-Javadoc)* @seeerDetails#isAccountNonExpired() */public booleanisAccountNonExpired() {return true;}/* (non-Javadoc)* @seeerDetails#isAccountNonLocked() */public booleanisAccountNonLocked() {return true;}/* (non-Javadoc)* @seeerDetails#isCredentialsNonExpired()*/public booleanisCredentialsNonExpired() {return true;}/* (non-Javadoc)* @see erDetails#isEnabled()*/public booleanisEnabled() {return (disabled==1?true:false);}/*** @return the id*/public Integer getId() {return id;}/*** @return the name*/public String getName() {return name;}/*** @return the disabled*/public intgetDisabled() {return disabled;}/*** @return the roles*/public Set<Role>getRoles() {return roles;}/*** @return the roleResources*/public Map<String, List<Resource>>getRoleResources() {// initroleResources for the first timeif(this.roleResources == null) {this.roleResources = new HashMap<String, List<Resource>>(); for(Role role : this.roles) {String roleName = role.getName();Set<Resource> resources = role.getResources();for(Resource resource : resources) {String key = roleName + "_" + resource.getType();if(!this.roleResources.containsKey(key)) {this.roleResources.put(key, new ArrayList<Resource>());}this.roleResources.get(key).add(resource);}}}return this.roleResources;}/*** @param id the id to set*/public void setId(Integer id) {this.id = id;}/*** @param name the name to set*/public void setName(String name) { = name;}/*** @param password the password to set */public void setPassword(String password) { this.password = password;}/*** @param disabled the disabled to set*/public void setDisabled(int disabled) {this.disabled = disabled;}/*** @param roles the roles to set*/public void setRoles(Set<Role> roles) {this.roles = roles;}}。
Spring Security 安全管理
Spring Security系统安全管理----编写人csx目录1. Spring Security安全框架介绍 (2)1.1 Spring Security核心概念 (2)1.1.1 Authentication (认证)对象 (2)1.1.2 SecurityContextHolder (3)1.1.3 AuthenticationManager (3)1.1.4 AccessDecissionManager (3)1.1.5 Interceptors(拦截器) (3)1.1.6 GrantedAuthority(权限) (3)1.2 Spring Security安全管理的原理 (4)1.2.1 Spring Security对一个请求的认证过程 (4)1.2.2 用户的认证过程 (5)2. 系统的安全管理方式 (6)3. 整合Spring Security (8)3.1 表设计 (8)3.2 与Spring Security集成说明 (9)3.2.1 身份认证 (9)3.2.2访问授权 (12)3.2.3 权限的配置及使用 (14)1.Spring Security安全框架介绍Spring Security(以下简称为SS)其前身是大名鼎鼎的ACEGI,后来正式合并至Spring框架,成为Spring框架中一员,由于它支持安全策略比较多,并且集成容易,现在也越来越多的系统采用它来进行安全管理。
本系统中也采用它的基于角色的管理策略,以实现系统灵活的安全管理要求。
1.1Spring Security核心概念1.1.1Authentication (认证)对象其实就是一个可以通过Spring Security的认证的身份证明。
如实现该接口的类UsernamePasswordAuthenticationToken,表示可以通过username及password作为身份验证。
Authentication对象包含了Principal 标识是哪一个对象,可以认为是用户Credentials 信任的对象,如密码Authorities 权限的集合,在我们的系统中可以认为是角色的集合(authorities要赋予给principal的)1.1.2SecurityContextHolder是Spring Security的核心对象,是安全上下文的访问的入口。
SpringSecurity使用详解(基本用法)
SpringSecurity使⽤详解(基本⽤法)Spring Security使⽤详解(基本⽤法)1,什么是 Spring Security ?Spring Security 是⼀个相对复杂的安全管理框架,功能⽐ Shiro 更加强⼤,权限控制细粒度更⾼,对 OAuth 2 的⽀持也更友好。
由于 Spring Security 源⾃ Spring 家族,因此可以和 Spring 框架⽆缝整合,特别是 Spring Boot 中提供的⾃动化配置⽅案,可以让 Spring Security 的使⽤更加便捷。
2,安装配置<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>3、开始测试:⾸先在项⽬添加⼀个简单的 /hello 接⼝:@RestControllerpublic class HelloController {@GetMapping("/hello")public String hello() {return "欢迎访问 ";}}接着启动项⽬,直接访问 /hello 接⼝则会⾃动跳转到登录页⾯(这个登录页⾯是由 Spring Security 提供的)(3)我们必须登录后才能访问 /hello 接⼝。
默认⽤户名是 user,⽽登录密码则在每次启动项⽬时随机⽣成,我们可以在项⽬启动⽇志中找到。
(4)登录后则会⾃动跳转到之前我访问的 /hello 接⼝:4,配置⽤户名和密码如果对默认的⽤户名和密码不满意,可以在 application.properties 中配置默认的⽤户名、密码和⾓⾊。
这样项⽬启动后就不会随机⽣成密码了,⽽是使⽤我们配置的⽤户、密码,并且登录后还具有⼀个 admin ⾓⾊(关于⾓⾊的⽤法再后⾯的⽂章会相信介绍)。
springsecurity教程
springsecurity教程Spring Security是一个基于Spring框架的安全性解决方案,用于保护Java应用程序中的身份验证和授权。
首先,您需要添加Spring Security的依赖项到您的项目中。
您可以通过Maven或Gradle来管理依赖。
在pom.xml(或build.gradle)文件中添加以下依赖项:```xml<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>```接下来,您需要配置Spring Security。
在Spring Boot应用程序中,默认的Spring Security配置会自动应用。
您可以通过在application.properties(或application.yml)文件中添加以下配置来自定义和覆盖默认配置:```yaml=adminer.password=admin```上述配置将在应用程序中创建一个名为“admin”的用户,密码也是“admin”。
在您的应用程序中,您可以使用`@EnableWebSecurity`注解启用Spring Security的Web安全性支持,并扩展`WebSecurityConfigurerAdapter`类来配置安全性规则。
```java@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/public/**").permitAll().anyRequest().authenticated().and().formLogin().loginPage("/login").permitAll().and().logout().permitAll();}}```上述配置中,我们允许对“/public/**”路径下的资源进行公共访问,其他所有请求都需要进行身份验证。
Spring Security 5.1 中文 参考手册 中文文档
VPN或IP安全性来确保只有经过授权的系统才能尝试连接。 在企业环境中,您可以部署一个DMZ,将面向公众的服务器与后端数据库和应用程序服务器分开。 您的操作系
统也将扮演重要角色,解决诸如以无特权用户身份运行进程等问题并最大限度提高文件系统安全性。 操作系统通常也会配置自己的防火墙。 希望在这个过程中的某个地方 你会试图阻止对系统的拒绝服务和暴力攻击。 入侵检测系统对于监视和响应攻击也特别有用,因为这些系统能够采取保护措施,例如实时阻止侵入TCP / IP地址。 转移到 更高层,您的Java虚拟机将有望配置为最大限度地减少授予不同Java类型的权限,然后您的应用程序将添加自己的问题特定于域的安全配置。 Spring Security使后面的这个 领域 - 应用程序的安全性更容易。 当然,您需要正确处理上面提到的所有安全层,以及包含每个层的管理因素。 这些管理因素的非详尽清单将包括安全公告监控,修补,人员审查,审计,变更控制,工程 管理系统,数据备份,灾难恢复,性能基准测试,负载监控,集中式日志记录,事件响应程序等。 由于Spring Security专注于帮助企业应用程序安全层,因此您会发现有多少不同的需求与业务问题域相同。 银行应用程序对电子商务应用程序有不同的需求。 电子商务应 用程序对企业销售人员自动化工具有不同的需求。 这些自定义要求使应用程序安全性变得有趣,富有挑战性和有益。 请首先阅读Chapter 1, Getting Started的全部内容。 这将向您介绍框架和基于命名空间的配置系统,您可以使用该系统快速启动和运行。 为了更好地理解Spring Security的 工作原理以及您可能需要使用的一些类,请阅读Part II, “Architecture and Implementation” 。 本指南的其余部分采用更传统的参考样式,旨在根据需要进行阅读。 我们还建 议您尽可能多地阅读应用程序安全问题。 Spring Security不是解决所有安全问题的万能药。 从一开始,应用程序的设计就要考虑到安全性,这一点很重要。 试图改造它并 不是一个好主意。 特别是,如果您正在构建Web应用程序,则应该意识到许多潜在的漏洞,例如跨站脚本,请求伪造和会话劫持,您应该从一开始就考虑这些漏洞。
SpringSecurity权限控制
SpringSecurity 权限控制Spring EL 权限表达式Spring Security 允许我们使⽤ Spring EL 表达式,来进⾏⽤户权限的控制,如果对应的表达式结果返回true,则表⽰拥有对应的权限,反之则⽆。
Spring Security 可⽤表达式对象的基类是 SecurityExpressionRoot注意: 表达式以下⾯为准, 黄⾊标注的 is 在使⽤时是要加上的表达式控制URL 权限权限控制操作拥有 sys:user 权限的⽤户,可以访问任意请求⽅式的 /userantMatchers("/user").hasAuthority("sys:user")拥有 sys:role 权限的⽤户,可以访问 get 请求⽅式的 /roleantMatchers(HttpMethod.GET, "/role").hasAuthority("sys:role")如果想同时满⾜多个表达式权限,要使⽤ access ⽅法来指定表达式如:拥有 sys:permission 权限或 ADMIN ⾓⾊,可以访问 get 请求⽅式的 /permission注意:指定⾓⾊标识后,底层会⾃动加上前缀 ROLE_ ,所以在给⽤户授权⾓⾊时需要加上前缀antMatchers(HttpMethod.GET, "/permission").access("hasAuthority('sys:permission') or hasAnyRole('ADMIN')") //⾓⾊会加上前缀 ROLE_,即真实是 ROLE_ADMIN基于注解控制⽅法级权限概述在Spring Security中实现⽅法级的安全性,最常见办法是使⽤特定的注解,将这些注解应⽤到需要保护的⽅法上。
spring security3 0 5安全配置手册
>retlif< >marap-txetnoc/< >eulav-marap/<lmx.*txetnoCnoitacilppa:htapssalc>eulav-marap< >eman-marap/<noitacoLgifnoCtxetnoc>eman-marap< >marap-txetnoc< >"dsx.4_2_ppa-bew/ee2j/sn/lmx/moc.nus.avaj//:ptth ee2j/sn/lmx/moc.nus.avaj//:ptth"=noitacoLamehcs:isx "ecnatsni-amehcSLMX/1002/gro.3w.www//:ptth"=isx:snlmx "ee2j/sn/lmx/moc.nus.avaj//:ptth"=snlmx "4.2"=noisrev ppa-bew< >?"8-FTU"=gnidocne "0.1"=noisrev lmx?< �样这是像来起看lmx.bew的到得终最。置配关相的gnirpS载加上加要还�器滤过 的到提刚刚们我置配要需了除中lmx.bew以所�的上之础基的gnirpS在立建是ytiruceS gnirpS为因 目项个整善完 .3.1 。源资的问访许允NIMDA_ELOR问访能不 而�源资的问访许允RESU_ELOR问访能只他以所�限权RESU_ELOR有拥只就户用resu�是的应对之与 。源资有所的问访许允RESU_ELOR 和NIMDA_ELOR问访以可后之陆登在户用nimda得使这�限权种两RESU_ELOR和NIMDA_ELOR有拥就 户用nimda的中子例�限权个多有拥时同以可户用个每。应对一一容内限权的义定中lru-tpecretni 面上与它�限权的有拥会将后之陆登户用个这了义定里这�seitirohtua是分部的要重最最 。取窃人他被码密户用免避 �式方密加的供提ytiruceS gnirpS用使会们我中子例的后之 �便方的示演前当了为是只这 �码密的应 对户用个两了义定文明用使们我�见起便简了为。resu和nimda�户用个两了义定中ecivres-resu:4 。容内的retoV 解讲细详会们我中分部的后以程教在�了以可就点一这住记要需只们我说来前目。理处ytiruceS gnirpS被会才串符字的缀前定特了含包有只�系联的缕万丝千着有制机retoV的中ytiruceS gnirpS 与这上际实�的头开_ELOR以是都符示标限权些这到意注以可家大�趣有较比分部限权的定指ssecca 。psj.nimda/问访能才户用的限权NIMDA_ELOR了有拥些那有只�说是就也�求请的psj.nimda/ 对理处置配的中lru-tpecretni个一第用使会ytiruceS gnirpS以所�面上在排lru-tpecretni 个一第为因但�求要足满都lru-tpecretni个两然虽�时psj.nimda/问访户用当�是就中 子例个这们我在。制控限权行进lru-tpecretni的件条合符个一第用使将统系�时lru-retpecretni 个多足满源资lru的问访户用当说是就�则原近就种一是的用采ytiruceS gnirpS�中用使际实在 。问访的源资lru有所中统系对 制控将它明说�**/符配通了用使个二第�问访的psj.nimda/对制控来用个一第�lru-retpecretni 个两的义定中子例。源资lru的似类组一定指符配通用使以可也�源资lru的定特个一定指中 nrettap在以可�源资lru的应对问访能才限权种何有具要需户用断判来lru-tpecretni用利们我:3 。eMrebmemer ,suomynona ,mrof括 包�制机制控限权的用常种几置配动自将'eurt'=gifnoc-otua。求请户用截拦何如置配分部ptth:2 。间空名命的供提ytiruceS gnirpS用使中lmx在明声:1
Spring_security_2权限安全管理
Spring Security 2安全管理方式一、该系统的安全管理方式是结合Spring Security 实现的。
二、系统需要实现的安全管理方式有:1. 登录时需要验证用户名和密码2. 登录时需要加上验证码3. 所有的数据展示及访问页面需要登录后才能访问4. 登录后的所有系统的访问URL均需要授权5. 多个用户不能使用同一个账号同时登陆系统6. 当用户点击注销后要实现浏览器的后退按钮后退的页面失效权限设计是采用基于角色控制的方式,用户需要访问系统的资源,首先必须要授予一个角色,而该角色具有访问系统资源的权限的能力,也可以认为是权限的集合。
因此,一个用户要访问系统的某个资源(如产品列表),则首先要授予一个能够访问产品列表资源的角色(如productAdmin)。
只要任一个用户拥有了该角色,即可以访问该资源。
系统的安全涉及到两个不同的概念,认证和授权。
前者是验证用户是否可以进入该系统。
用户进入系统的时候,首先要进行第一个操作就是进行身份认证,即Authentication。
在系统中一般表现为用户用账号跟密码登录。
如果都正确了,则可以登录系统。
【说明】在现实中你可以这样理解,员工在进入公司之前,需要进行身份的确认。
身份确认通过后,则可以进入公司。
进入公司后,并不代表可以随便进入公司的每个办公室。
这时就需要看当前员工具有哪些角色,即授权。
授权则是关于确认用户是否允许执行一个特定的操作。
如当前员工是总经理,则可以进入总经理办公室,并且可以进入普通员工的办公区域。
是因为总经理已经授权可以出入这些地方。
在本系统中,权限表现为功能菜单及系统访问的URL。
因而用户、角色、权限、功能菜单之间的关系可以用如下的图描述一个用户可以有多个角色,每个角色有多个菜单,每个菜单有多个功能,每个功能会对应多个系统访问的URL资源。
基于以上思想,数据库中的表设计:app_user 系统用户表,放置系统的所有用户。
user_role 用户角色中间表,用户所拥有的角色。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
S p r i n g S e c u r i t y安全权限管理手册参考文献:1、security权限管理手册。
2、spring 权限管理手册3、spring的相关资料。
本文档内容仅仅作为公司权限管理资料用,对于企业来说,权限管理将是系统中的非常重要的一个模块,权限的设计也是参考相关资料进行整理和补充。
系统将通过数据库进行管理用户权限。
权限管理搭建要的问题:1、区分Authentication(验证)与 Authorization(授权)验证这个用户是谁?用户身份可靠吗?授权某用户A是否可以访问资源R某用户A是否可以执行M操作某用户A是否可以对资源R执行M操作2、SS中的验证特点支持多种验证方式支持多种加密格式支持组件的扩展和替换可以本地化输出信息3、SS中的授权特点支持多种仲裁方式支持组件的扩展和替换支持对页面访问、方法访问、对象访问的授权。
4、SS核心安全实现Web安全通过配置Servlet Filter激活SS中的过滤器链实现Session一致性验证实现免登陆验证(Remember-Me验证)提供一系列标签库进行页面元素的安全控制方法安全通过AOP模式实现安全代理Web安全与方法安全均可以使用表达式语言定义访问规则5、配置SS配置,应用安全过滤器配置Spring,验证与授权部分在web页面中获取用户身份在web页面中应用安全标签库实现方法级安全6、配置7、Spring配置文件中设置命名空间8、通过数据库验证用户身份9、完善web页面验证规则10、自定义验证配置11、本地化消息输出(国际化)根据公司项目的开发要求和集合spring 功能,公司将通过数据库进行对用户身份验证和授权,系统将建立5个基础表进行对权利的管理。
第一部分数据库设计1、表设计create table pub_users(user_id varchar(32),user_account varchar(30),user_name varchar(40),user_password varchar(100),user_desc varchar(100),enabled int,issys int);alter table pub_users add constraint pk_pub_users primary key(user_id); create table pub_authorities(authority_id varchar(32),authority_name varchar(40),authority_desc varchar(100),enabled int,issys intalter table pub_authorities add constraint pk_pub_authorities primary key(authority_id);create table pub_roles(role_id varchar(32),role_name varchar(40),role_desc varchar(100),enabled int,issys int);alter table pub_roles add constraint pk_pub_roles primary key(role_id);create table pub_resources(resource_id varchar(32),resource_name varchar(100),resource_desc varchar(100),resource_type varchar(40),resource_string varchar(200),priority int,enabled int,issys int);alter table pub_resources add constraint pk_pub_resources primary key(resource_id);create table pub_users_roles(id numeric(12,0) IDENTITY NOT NULL,user_id varchar(32),role_id varchar(32),enabled int);alter table pub_users_roles add constraint pk_pub_users_roles primary key(id); alter table pub_users_roles add constraint fk_users_roles_users foreign key(user_id) references pub_users(user_id);alter table pub_users_roles add constraint fk_users_roles_roles foreign key(role_id) references pub_roles(role_id);create table pub_roles_authorities(id numeric(12,0) IDENTITY NOT NULL,role_id varchar(32),authority_id varchar(32),enabled int);alter table pub_roles_authorities add constraint pk_pub_roles_authorities primary key(id);alter table pub_roles_authorities add constraint fk_pub_roles_authorities_authorities foreign key(authority_id) references pub_authorities(authority_id);alter table pub_roles_authorities add constraint fk_pub_roles_authorities_rolescreate table pub_authorities_resources(id numeric(12,0) IDENTITY NOT NULL,authority_id varchar(32),resource_id varchar(32),enabled int);alter table pub_authorities_resources add constraint pk_pub_authorities_resources primary key(id);alter table pub_authorities_resources add constraint fk_pub_authorities_resources_authorities foreign key(authority_id) references pub_authorities(authority_id);alter table pub_authorities_resources add constraint fk_pub_authorities_resources_resources foreign key(resource_id) references pub_resources(resource_id);3、E-R图如下:第二部分 WEB数据库整合提示:相关代码请参考项目模块1、将数据库表结构和Hibernate建立映射,本系统采用annotation进行对数据库进行零配置处理(请参考hibernate映射),如图。
2、建立权限的Dao层。
3、建立权限的Service层4、配置<?xml version=""encoding="UTF-8"?><web-app version=""xmlns=""xmlns:xsi=""xsi:schemaLocation=""><display-name>rstframe</display-name><context-param><param-name>webAppRootKey</param-name><param-value></param-value></context-param><context-param><param-name>log4jConfigLocation</param-name><param-value>classpath:</param-value></context-param><context-param><param-name>log4jRefreshInterval</param-name><param-value>60000</param-value></context-param><!-- Spring ApplicationContext配置文件的路径,可使用通配符,多个路径用,号分隔此参数用于后面的Spring Context Loader --><context-param><param-value>classpath*:/,classpath*:/</param-value></context-param><!-- Character Encoding filter --><filter><filter-name>encodingFilter</filter-name><filter-class></filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param></filter><filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- SpringSide's Hibernate Open Session In View filter--><filter><filter-name>hibernateOpenSessionInViewFilter</filter-name> <filter-class></filter-class><init-param><param-name>excludeSuffixs</param-name><param-value>js,css,jpg,gif</param-value></init-param></filter><filter-mapping><filter-name>hibernateOpenSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern></filter-mapping><!-- SpringSecurity filter--><filter><filter-name>springSecurityFilterChain</filter-name><filter-class></filter><filter-mapping><filter-name>springSecurityFilterChain</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- Struts2 filter, actionPackages --><filter><filter-name>struts2Filter</filter-name><filter-class></filter><filter-mapping><filter-name>struts2Filter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!--Spring的ApplicationContext 载入 --><listener><listener-class></listener-class></listener><listener><listener-class></listener-class></listener><!-- Spring 刷新Introspector防止内存泄露 --><listener><listener-class></listener-class></listener><!-- 防止多人登陆 ,控制一个用户只能登录一次,不能在其他地方重新登录--> <listener><listener-class></listener-class></listener><!-- session超时定义,单位为分钟 --><session-config><session-timeout>20</session-timeout></session-config><welcome-file-list><welcome-file></welcome-file></welcome-file-list><!-- error page --><error-page><exception-type><location>/common/</location></error-page><error-page><error-code>500</error-code><location>/common/</location></error-page><error-page><error-code>404</error-code><location>/common/</location></error-page><error-page><location>/common/</location></error-page><jsp-config><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location> </taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location> </taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location> </taglib><!--loushang tld--><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib><!-- loushang end --><taglib><taglib-uri>/WEB-INF/</taglib-uri><taglib-location>/WEB-INF/tlds/</taglib-location></taglib></jsp-config><mime-mapping><extension>rar</extension><mime-type>application/rar</mime-type></mime-mapping></web-app>5、配置spring 中的xml文件文件名:<?xml version=""encoding="UTF-8"?><beans:beans xmlns=""xmlns:beans=""xmlns:xsi=""xsi:schemaLocation=" "><beans:description>SpringSecurity安全配置</beans:description> <!-- http安全配置 --><http auto-config="true"><intercept-url pattern="/css/**"filters="none"/><intercept-url pattern="/images/**"filters="none"/><intercept-url pattern="/js/**"filters="none"/><intercept-url pattern="/"filters="none"/><intercept-url pattern="/" access="ROLE_USER"/><intercept-url pattern="/" access="ROLE_ADAMIN"/>--><form-login login-page="/"default-target-url="/"authentication-failure-url="/?error=1"/><!-- 尝试访问没有权限的页面时跳转的页面 --><access-denied-handler error-page="/common/"/><logout logout-success-url="/" /><session-management><concurrency-control max-sessions="1"error-if-maximum-exceeded="true"/></session-management><!-- 增加一个filter,这点与Acegi是不一样的,不能修改默认的filter了,这个filter位于FILTER_SECURITY_INTERCEPTOR之前 --><custom-filter ref="myFilter"before="FILTER_SECURITY_INTERCEPTOR"/> </http><!-- 一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,我们的所有控制将在这三个类中实现,解释详见具体配置 --><beans:bean id="myFilter"class=""><beans:property name="authenticationManager"ref="authenticationManager"/><beans:property name="accessDecisionManager"ref="myAccessDecisionManagerBean"/><beans:property name="securityMetadataSource"ref="mySecurityMetadataSource"/></beans:bean><!-- 验证配置,认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 --> <authentication-manager alias="authenticationManager"><authentication-provider user-service-ref="userDetailsService"><!--<s:password-encoder hash="sha" />--></authentication-provider></authentication-manager><!-- 项目实现的用户查询服务,将用户信息查询出来 --><beans:bean id="userDetailsService"class=""/><!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 --><beans:bean id="myAccessDecisionManagerBean"class=""></beans:bean><!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色访问--><beans:bean id="mySecurityMetadataSource"class=""></beans:bean><!-- 定义国际化 --><beans:bean id="messageSource"class=""><beans:property name="basename"value="classpath:org/springframework/security/messages_zh_CN"/></beans:bean></beans:beans>第三部分的实现这是项目的主体部分:这四个类说明如下。