Java Web系列:Spring Security 基础

Java Web系列:Spring Security 基础,第1张

概述Spring Security虽然比JAAS进步很大,但还是先天不足,达不到ASP.NET中的认证和授权的方便快捷。这里演示登录、注销、记住我的常规功能,认证上自定义提供程序避免对数据库的依赖,授权上自定义提供程序消除从缓存加载角色信息造成的角色变更无效副作用。1.基于java config的Spring Security基础配置(1)使用AbstractSecurityWebApplicationInitializer集成到Spring MVC1 public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {2 }(2)使用匿名类在WebSecurityConfigurerAdapter自定义AuthenticationProvider、UserDetailsService、SecurityContextRepository。1 @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)2 @EnableWebSecurity3 public class SecurityConfig extends WebSecurityConfigurerAdapter {45 @Override6 protected void configure(HttpSecurity http) throws Exception {7 http.authorizeRequests().antMatchers("/account**", "/admin**").authenticated();8 http.formLogin().usernameParameter("userName").passwordParameter("password").loginPage("/login")9 .loginProcessingUrl("/login").successHandler(new SavedRequestAwareAuthenticationSuccessHandler()).and()10 .logout().logoutUrl("/logout").logoutSuccessUrl("/");11 http.rememberMe().rememberMeParameter("rememberMe");12 http.csrf().disable();13 http.setSharedObject(SecurityContextRepository.class, new SecurityContextRepository() {1415 private HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();1617 @Override18 public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {19 SecurityContext context = this.repo.loadContext(requestResponseHolder);20 if (context != null && context.getAuthentication() != null) {21 Membership membership = new Membership();22 String username = context.getAuthentication().getPrincipal().toString();23 String[] roles = membership.getRoles(username);24 context.getAuthentication().getAuthorities();25 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username,26 "password", convertStringArrayToAuthorities(roles));27 context.setAuthentication(token);28 System.out.println("check user role");29 }30 return context;31 }3233 @Override34 public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {35 this.repo.saveContext(context, request, response);36 }3738 @Override39 public boolean containsContext(HttpServletRequest request) {40 return this.repo.containsContext(request);41 }42 });43 }4445 @Autowired46 @Override47 protected void configure(AuthenticationManagerBuilder auth) throws Exception {48 auth.authenticationProvider(new AuthenticationProvider() {4950 @Override51 public Authentication authenticate(Authentication authentication) throws AuthenticationException {52 Membership membership = new Membership();53 String username = authentication.getName();54 String password = authentication.getCredentials().toString();55 if (membership.validateUser(username, password)) {56 String[] roles = membership.getRoles(username);57 UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username,58 "password", convertStringArrayToAuthorities(roles));59 return token;60 }61 return null;62 }6364 @Override65 public boolean supports(Class<?> authentication) {66 return authentication.equals(UsernamePasswordAuthenticationToken.class);67 }6869 });70 auth.userDetailsService(new UserDetailsService() {7172 @Override73 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {74 Membership membership = new Membership();75 if (membership.hasUser(username)) {76 UserDetails user = new User(username, "password",77 convertStringArrayToAuthorities(membership.getRoles(username)));78 return user;79 }80 return null;81 }82 });83 }8485 public Collection<? extends GrantedAuthority> convertStringArrayToAuthorities(String[] roles) {86 List<SimpleGrantedAuthority> list = new ArrayList<SimpleGrantedAuthority>();87 for (String role : roles) {88 list.add(new SimpleGrantedAuthority(role));89 }90 return list;91 }92 }2.使用@PreAuthorize在Controller级别通过角色控制权限(1)使用@PreAuthorize("isAuthenticated()")注解验证登录1

Spring Security虽然比JAAS进步很大,但还是先天不足,达不到ASP.NET中的认证和授权的方便快捷。这里演示登录、注销、记住我的常规功能,认证上自定义提供程序避免对数据库的依赖,授权上自定义提供程序消除从缓存加载角色信息造成的角色变更无效副作用。

1.基于java config的Spring Security基础配置

(1)使用AbstractSecurityWebApplicationInitializer集成到Spring MVC

SecurityInitializer }

@EnableGlobalMethodSecurity(securedEnabled = ,prePostEnabled = SecurityConfig configure(httpSecurity http) http.authorizeRequests().antMatchers("/account**","/admin**" http.formLogin().usernameParameter("username").passwordParameter("password").loginPage("/login" .loginProcessingUrl("/login").successHandler( .logout().logoutUrl("/logout").logoutSuccessUrl("/" http.rememberMe().rememberMeParameter("rememberMe" http.setSharedobject(SecurityContextRepository., httpSessionSecurityContextRepository repo = SecurityContext context = (context != && context.getAuthentication() != Membership membership = String username = String[] roles = UsernamePasswordAuthenticationToken token = "password" System.out.println("check user role" configure(AuthenticationManagerBuilder auth) auth.authenticationProvIDer( Authentication authenticate(Authentication authentication) Membership membership = String username = String password = String[] roles = UsernamePasswordAuthenticationToken token = "password" supports(Class authentication.equals(UsernamePasswordAuthenticationToken. auth.userDetailsService( UserDetails loadUserByUsername(String username) Membership membership = UserDetails user = User(username,"password" Collection GrantedAuthority> List List = ArrayList List.add( }2.使用@PreAuthorize在Controller级别通过角色控制权限

(1)使用@PreAuthorize("isAuthenticated()")注解验证登录

@PreAuthorize("isAuthenticated()" @RequestMapPing(value = "/account" "account" }

(2)使用@PreAuthorize("hasAuthority('admin')")注解验证角色

@PreAuthorize("hasAuthority('admin')" @RequestMapPing("/admin" "admin" }3.登录和注销功能

注销直接使用内置功能,登录可以自定义控制器和视图。

@RequestMapPing(value = "/login" String login(@RequestParam(value = "error",required = @modelattribute("model" (error != result.rejectValue("username","","InvalID username and password!" "login" }

视图:

Getting Started: Serving Web Content Login Form has errors username password rememberMe 4.Spring Security核心对象

验证和授权的核心的ASP.NET肯定是httpModule,Java是Filter,这没什么可说的,到现在两套组合(httpApplicaiton+httpModule+httpHandler)(ServletContext+Filter+Servlet)的核心概念已经熟练了。

(1)安全上下文

ASP.NET中我们可以通过httpContext.User获取IPrincipal的实例,这是通过httpModuel(FormsAuthenticationModule)机制实现的。Spring Security中获取SecurityContext也是通过对应的Filter(SecurityContextPersistenceFilter)机制实现的。SecurityContextPersistenceFilter将功能委托给的实例实现,因此我们在上文自定义了SecurityContextRepository实现,刷新其中的角色信息。

(2)身份认证提供程序

AuthenticationProvIDer对象的authenticate方法验证并返回对象。Authentication对象是Java的Principal接口的子接口。上文自定义的AuthenticationProvIDer只是简单的将用户名username作为Authentication的实现类UsernamePasswordAuthenticationToken构造函数的参数传递,如果需要也可以传递其他object,调用时通过SecurityContextHolder.getContext().getAuthentication().getPrincipal()获取。

(3)用户信息提供程序

只有在AuthenticationProvIDer的实现中采用了UserDetailsService用于验证,UserDetailsService才是必须的。UserDetailsService返回一个用对象。在AuthenticationProvIDer中调用UserDetailsService,将UserDetails对象作为Principal参数传递给Authentication对象,这样我们可以在Controller中通过如下语句获取UserDetails对象。事实上只需要传递用户名作为Principal参数是最实用的,多搞一个自定义UserDetails还不如自定义POJO从Service中通过用户名返回信息来的干净快捷。即使使用UserDetails对象也不一定要使用UserDetailsService,可以直接在AuthenticationProvIDer中构造并传递UserDetails对象。上面代码的UserDetailsService只是作为演示,实际上不会被调用。

UserDetails userDetails = (UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();参考

(1)http://docs.spring.io/autorepo/docs/spring-security/3.2.x/guIDes/hellomvc.HTML

(2)http://docs.spring.io/spring-security/site/docs/4.0.4.CI-SNAPSHOT/reference/HTMLsingle/

(3)http://docs.spring.io/spring/docs/current/spring-framework-reference/HTML/vIEw.HTML

JAAS对核心的数据结构不关注,定义了一堆还不如没有的过程依赖,Spring Security虽然改进了易用性,但从JAAS中继承了不切实际的幻想风格。提供核心数据结构和接口就行了,非要从密码加密到用户信息获取一路跑偏到对缓存和数据库都能产生依赖,Spring基于Object的依赖注入已经不适用了,Spring Security又偏离了核心。内置的不合理,外置的很难用,整合这个词就是整一堆框架合起来才能凑合用。什么时候基于类型的依赖注入框架能取代Spring、基于数据结构的验证框架能取代Spring Security,Java Web开发的生产力估计会提高一些。到现在我还没有找到可用的基于注解的前后端统一验证框架,没有这个东西,对于快速制作演示模型简直是灾难。不管怎么说,SSH这些东西至少要对其基础配置和核心对象有整体上的把握,至少要能快速定位开发中遇到的问题并基于对源代码的了解能应对实际中出现的大部分技术问题才行。

总结

以上是内存溢出为你收集整理的Java Web系列:Spring Security 基础全部内容,希望文章能够帮你解决Java Web系列:Spring Security 基础所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1270034.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存