spring security3 实现自定义管理权限
2017-03-26 00:00
162 查看
今天有个群友问了下ss3的问题,他主要是登陆实现权限的校验的顺序不清晰,当初我学这个框架的时候也是被ss3登陆校验权限的顺序困扰了几天。下面是我一点理解,有错的话还望指正一下。
其实,要实现自定义权限的话只有几个关键的类和接口,只要搞清楚他们的顺序就行了。
1、你可以初始化话容器的时候就加载资源和权限列表,这个在实现FilterInvocationSecurityMetadataSource接口的类里,定一个全局的静态map,以url为key,所需权限(集合)为value,装进这个静态map。
2、登陆。登陆的action在spring配置文件里配好。这个action会直接到继承UsernamePasswordAuthenticationFilter类的一个重写的attemptAuthentication方法里,把你输入username和password(加入配了MD5加密security3会自动帮你加密)和数据比对,如果存在这个username和password,进入第3步(这是后没有退出这个attemptAuthentication方法)。没有这个username和password的话直接抛异常和终止此次登陆。
3、如果username和password存在,会进入到实现UserDetailsService接口的类里的一个重写的loadUserByUsername方法,这个方法里会把该username所有拥有的权限设为安全权限然后返回一个UserDetails类型的结果。这是返回到第二步中的attemptAuthentication中,把这这个认证了得安全实体有所拥有的权限以Authentication类型返回。共第五步调用。
4、登陆认证成功后会有一个action(这个action在spring配置文件里配置),这个action是第一个url权限认证(假设这个action需要权限认证),这个请求会进入到实现了FilterInvocationSecurityMetadataSource接口的类里的一个重写的getAttributes方法,将第1步中的资源权限列表map中get出来,返回Collection<ConfigAttribute>类型的结果,共第5部调用。
5,第4步执行完之后会进入实现类AccessDecisionManager接口的类的一个重写decide方法,在这个方法中会将第3步中返回的Authentication和第4步中返回的Collection<ConfigAttribute>进行比对。比对成功则可以访问,比对不成功会跳转一个页面(这个页面也是在spring配置文件中配置)。
至此,已经完成了登陆的验证并成功执行一个action。
当然,你可以在登陆成功后添加一些你自己业务,比如说记录登陆次数和登陆ip,这需要实现security3的一些接口,并配置在spring配置文件里。
下面是所用到的一些关键的类
1、实现了FilterInvocationSecurityMetadataSource接口的类
2、继承了UsernamePasswordAuthenticationFilter的类
3、实现了UserDetailsService接口的类
4、实现了AccessDecisionManager接口的类
敲这些文字敲得好辛苦啊……不喜勿喷哈
其实,要实现自定义权限的话只有几个关键的类和接口,只要搞清楚他们的顺序就行了。
1、你可以初始化话容器的时候就加载资源和权限列表,这个在实现FilterInvocationSecurityMetadataSource接口的类里,定一个全局的静态map,以url为key,所需权限(集合)为value,装进这个静态map。
2、登陆。登陆的action在spring配置文件里配好。这个action会直接到继承UsernamePasswordAuthenticationFilter类的一个重写的attemptAuthentication方法里,把你输入username和password(加入配了MD5加密security3会自动帮你加密)和数据比对,如果存在这个username和password,进入第3步(这是后没有退出这个attemptAuthentication方法)。没有这个username和password的话直接抛异常和终止此次登陆。
3、如果username和password存在,会进入到实现UserDetailsService接口的类里的一个重写的loadUserByUsername方法,这个方法里会把该username所有拥有的权限设为安全权限然后返回一个UserDetails类型的结果。这是返回到第二步中的attemptAuthentication中,把这这个认证了得安全实体有所拥有的权限以Authentication类型返回。共第五步调用。
4、登陆认证成功后会有一个action(这个action在spring配置文件里配置),这个action是第一个url权限认证(假设这个action需要权限认证),这个请求会进入到实现了FilterInvocationSecurityMetadataSource接口的类里的一个重写的getAttributes方法,将第1步中的资源权限列表map中get出来,返回Collection<ConfigAttribute>类型的结果,共第5部调用。
5,第4步执行完之后会进入实现类AccessDecisionManager接口的类的一个重写decide方法,在这个方法中会将第3步中返回的Authentication和第4步中返回的Collection<ConfigAttribute>进行比对。比对成功则可以访问,比对不成功会跳转一个页面(这个页面也是在spring配置文件中配置)。
至此,已经完成了登陆的验证并成功执行一个action。
当然,你可以在登陆成功后添加一些你自己业务,比如说记录登陆次数和登陆ip,这需要实现security3的一些接口,并配置在spring配置文件里。
下面是所用到的一些关键的类
1、实现了FilterInvocationSecurityMetadataSource接口的类
/** * @Description : 描述 * @author YangXuan *@email 364105996@qq.com * @date Aug 6, 2013 8:56:44 PM */ public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource { public MySecurityMetadataSource(ResourcesDao resourcesDao, RolesDao rolesDao) { this.resourcesDao = resourcesDao; this.rolesDao = rolesDao; this.loadResourceDefine(); } private ResourcesDao resourcesDao; private RolesDao rolesDao; private RequestMatcher requestMatcher; private String matcher = "ant"; public ResourcesDao getResourcesDao() { return resourcesDao; } public void setResourcesDao(ResourcesDao resourcesDao) { this.resourcesDao = resourcesDao; } public RolesDao getRolesDao() { return rolesDao; } public void setRolesDao(RolesDao rolesDao) { this.rolesDao = rolesDao; } public void setRequestMatcher(RequestMatcher requestMatcher) { this.requestMatcher = requestMatcher; } public void setMatcher(String matcher) { this.matcher = matcher; } // 返回所请求资源所需要的权限 public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { HttpServletRequest request = ((FilterInvocation) object).getRequest(); String requestUrl = ((FilterInvocation) object).getRequestUrl(); System.out.println("requestUrl is " + requestUrl); if (resourceMap == null) { loadResourceDefine(); } Set<String> urlMatch = resourceMap.keySet(); for (String url : urlMatch) { if (matcher.toLowerCase().equals("ant")) { requestMatcher = new AntPathRequestMatcher(url); } if (matcher.toLowerCase().equals("regex")) { requestMatcher = new RegexRequestMatcher(url, request.getMethod(), true); } if (requestMatcher.matches(request)) { return resourceMap.get(url); } } return null; } public Collection<ConfigAttribute> getAllConfigAttributes() { return null; } public boolean supports(Class<?> clazz) { return true; } public static Map<String, Collection<ConfigAttribute>> resourceMap = null; private void loadResourceDefine() { System.out .println(">>>>>>>>>>loadResourceDefine()---successfully<<<<<<<<<<"); if (resourceMap == null) { resourceMap = new HashMap<String, Collection<ConfigAttribute>>(); List<Resources> resources = this.resourcesDao.findAllResources(); for (Resources resource : resources) { /*System.out.println(resource.getId() + "---" + resource.getUrl() + "---" + resource.getDescr() + "---" + resource.isEnabled());*/ List<Roles> roles = this.rolesDao .findRolesByResourcesId(resource.getId()); Collection<ConfigAttribute> configAttributes = new HashSet<ConfigAttribute>(); for (Roles role : roles) { configAttributes .add(new SecurityConfig(role.getRoleName())); } resourceMap.put(resource.getUrl(), configAttributes); } } } }
2、继承了UsernamePasswordAuthenticationFilter的类
/** * @Description : 描述 * @author YangXuan *@email 364105996@qq.com * @date Aug 6, 2013 8:57:45 PM */ public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { // 定义从前台接收参数的 属性名称 private String validationParameter = "validation"; public void setValidationParameter(String validationParameter) { this.validationParameter = validationParameter; } private boolean openValidation = true; public void setOpenValidation(boolean openValidation) { this.openValidation = openValidation; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { if (!request.getMethod().equals("POST")) { throw new AuthenticationServiceException( "Authentication method not supported: " + request.getMethod()); } String username = obtainUsername(request).trim(); String password = obtainPassword(request).trim(); // 验证码validation是否正确 if (openValidation) { checkValidateCode(request); } // 实现 Authentication,这里装进去的password会通过spring的MD5加密,然后实现校验 UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( username, password); // 允许子类设置详细属性 setDetails(request, authRequest); // 运行UserDetailsService的loadUserByUsername 再次封装Authentication return this.getAuthenticationManager().authenticate(authRequest); } @Override protected String obtainUsername(HttpServletRequest request) { Object obj = request.getParameter(getUsernameParameter()); return null == obj ? "" : obj.toString(); } @Override protected String obtainPassword(HttpServletRequest request) { Object obj = request.getParameter(getPasswordParameter()); return null == obj ? "" : obj.toString(); } protected String obtainValidationString(HttpServletRequest request) { Object obj = request.getParameter(validationParameter); return null == obj ? "" : obj.toString(); } public void checkValidateCode(HttpServletRequest request) { String jcaptchaCode = obtainValidationString(request).trim() .toUpperCase(); //获取前台的验证码输入值 if (null == jcaptchaCode || jcaptchaCode.equals("")) throw new BadCredentialsException("验证码超时!!!"); boolean b = CaptchaServiceSingleton.getInstance() .validateResponseForID(request.getSession().getId(), jcaptchaCode); if (!b) throw new BadCredentialsException("验证码不匹配!!!"); } }
3、实现了UserDetailsService接口的类
/** * @Description : 描述 * @author YangXuan *@email 364105996@qq.com * @date Aug 6, 2013 8:58:30 PM */ public class MyUserDetailServiceImpl implements UserDetailsService { private UsersDao usersDao; private RolesDao rolesDao; public UsersDao getUsersDao() { return usersDao; } public void setUsersDao(UsersDao usersDao) { this.usersDao = usersDao; } public RolesDao getRolesDao() { return rolesDao; } public void setRolesDao(RolesDao rolesDao) { this.rolesDao = rolesDao; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { Users users = this.usersDao.findByName(username); Set<GrantedAuthority> grantedAuths = obtionGrantedAuthorities(users); users.setAuthorities(grantedAuths); return users; } private Set<GrantedAuthority> obtionGrantedAuthorities(Users user) { Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>(); List<Roles> roles = this.rolesDao.findRolesByUsersId(user.getId()); for (Roles role : roles) { grantedAuthorities.add(new SimpleGrantedAuthority(role .getRoleName())); } return grantedAuthorities; } }
4、实现了AccessDecisionManager接口的类
/** * @Description : 描述 * @author YangXuan *@email 364105996@qq.com * @date Aug 6, 2013 8:59:02 PM */ public class MyAccessDecisionManager implements AccessDecisionManager { public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { if (configAttributes == null) { return; } Iterator<ConfigAttribute> iterator = configAttributes.iterator(); while (iterator.hasNext()) { ConfigAttribute configAttribute = iterator.next(); String needPermission = configAttribute.getAttribute(); for (GrantedAuthority ga : authentication.getAuthorities()) { if (needPermission.equals(ga.getAuthority())) { return; } } } // 没有权限让我们去捕捉 throw new AccessDeniedException(" No authority to access!"); } public boolean supports(ConfigAttribute attribute) { return true; } public boolean supports(Class<?> clazz) { return true; } }
敲这些文字敲得好辛苦啊……不喜勿喷哈
相关文章推荐
- 【Spring Security】三、自定义数据库实现对用户信息和权限信息的管理
- spring security3 实现自定义管理权限
- 模块管理常规功能自定义系统的设计与实现(05--权限和菜单)
- Spring Security教程(8)---- 自定义决策管理器及修改权限前缀
- spring之使用Spring Security实现权限管理
- 自定义注解实现权限管理框架或其它功能扩充
- Spring Security教程(8)---- 自定义决策管理器及修改权限前缀
- 使用Spring Security实现权限管理
- Spring Security实现权限管理
- 使用Spring Security实现权限管理
- springAOP与自定义注解实现细粒度权限控制管理
- MVC 自定义AuthorizeAttribute实现权限管理
- 权限管理(java+struts2(自定义标签)实现)--------->全代码演示
- 使用Spring Security实现权限管理
- 使用Spring Security实现权限管理
- 权限管理之基于ACL的实现:自定义JSTL函数实现即时认证
- 模块管理常规功能自定义系统的设计与实现(32--权限设计[2])
- 使用Spring Security实现权限管理
- MVC 自定义AuthorizeAttribute实现权限管理
- Spring security实现权限管理