zoukankan      html  css  js  c++  java
  • 更加优雅地配置Spring Securiy(使用Java配置和注解)

    Spring Security 借助一系列Servlet Filter 来提供安全性功能,但是借助Spring的小技巧,我们只需要配置一个Filer就可以了,DelegatingFilterProxy是一个特殊的Servlet Filter,它本身所做的工作并不多,只是将工作委托给一个javax.servlet.Filter 的实现类,这个实现类作为一个bean注册再Spring应用的上下文中。

      如果了解过用xml配置spring security的朋友就知道,用基于xml配置Spring Security过程繁琐,而且不容易学习和入门,但是基于javaConfig和注解则大大简化了这一配置,下面我们来看看是如何用java的方式配置Spring Security

      首先我们需要配置DelegatingFilterProxy,我们只需要拓展一个新类,该类实现了WebApplicationInitializer,因此Spring会发现它并用他在Web容器中注册DelegatingFilterProxy。

      

    public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer {
    }

      接下来我们需要启用Web安全性功能,也是只需要拓展一个类,Spring Security 必须配置在一个实现了WebSecurityConfigurer 的bean中,或者拓展WebSecurityConfigurerAdapter 。在Spring 应用上下文中,任何实现了WebSecurityConfigurerAdapter 的bean都可以用来配置Spring Security。常用的配置已贴上,也全都写上了对应的注释。

     

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private UserDetailServiceImpl userDetailService;
        //对每个请求进行细粒度安全性控制的关键在于重载一下方法
        @Override
        protected void configure(HttpSecurity http) throws Exception {
                http
                        .authorizeRequests()//该方法所返回的对象的方法来配置请求级别的安全细节
                            .antMatchers("/login")
                            .permitAll()//对于登录路径不进行拦截
                            .antMatchers("/show").authenticated()//authenticated()表示允许过的用户访问
                        .and()
                        .formLogin()//配置登录页面
                            .loginPage("/login")//登录页面的访问路径
                            .loginProcessingUrl("/check")//登录页面下表单提交的路径
                            .failureUrl("/login")//登录失败后跳转的路径
                            .defaultSuccessUrl("/show")//登录成功后默认跳转的路径
                        .and()
                        .csrf()//启用防跨站伪请求攻击,默认启用
                        .and()
                            .logout()//用户退出操作
                                .logoutUrl("/logout")//用户退出所访问的路径,需要使用Post方式
                                .permitAll()
                                .logoutSuccessUrl("/login?logout=true")
                        .and()
                            .authorizeRequests()
    //                    //定义路径保护的配置方法
    //                         .antMatchers(HttpMethod.GET,"/admin")
    //                        .authenticated()
                            .antMatchers(HttpMethod.GET,"/message/**","/object/**").hasRole("USER")
                            .anyRequest().permitAll()
                        .and()
                            .rememberMe()//启用记住我功能
                                .tokenValiditySeconds(2419200)
                ;
        }
        //配置Spring Security的Filter链
        @Override
        public void configure(WebSecurity web) throws Exception {
            super.configure(web);
        }
        //配置user-detail服务
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailService)
                .passwordEncoder(new StandardPasswordEncoder("53cr3t"))//密码加密方式
    
            ;
    //        auth.inMemoryAuthentication() //内置用户
    //                .withUser("user").password("user").roles("USER");
        }
    }

      需要注意的有几点,如果是用xml配置的springmvc环境下,基于javaConfig和注解配置Spring Security同样适用,只需要确保Spring的上下文能够扫描到上述的两个类即可。

      如果在JSP页面下使用Spring的表单标签,该标签默认会自动添加隐藏的CSRF token标签,即防跨站伪请求攻击,如果没有使用Spring的表单标签,则需要手动添加以下标签,尤其是进行logout登出时表单提交,在Form标签内必须保护以下内容

      

    <input type="hiden"
                name="${_csrf.parameterName}"
                value="${_csrf.token}"}

      下面是登录页面

      

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
    <html>
    <head>
        <title>login</title>
    </head>
    <body>
    <sf:form action="check" method="post" commandName="user" >
        用户名:<sf:input path="username"></sf:input>
        password:<sf:password path="password"></sf:password>
        <input id="remember_me" name="remember-me" type="checkbox">
        <label for="remember_me" class="inline">Remember me</label>
    
        <input type="submit" value="提交" >
    
    </sf:form>
    </body>
    </html>

      登出页面

      

    <%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ taglib prefix="sf" uri="http://www.springframework.org/tags/form" %>
    <html>
    <head>
        <title>User Manager</title>
    </head>
    <body>
       
      <sf:form id="logoutForm" action="${ctx}/logout" method="post">
    <a href="#" onclick="document.getElementById('logoutForm').submit();">注销</a>
    </sf:form>
    </body>
    </html>

      如果我们想要配置自定义认证和授权服务,则需要实现UserDetailsService

      

    public class UserDetailServiceImpl implements UserDetailsService {
        private static Logger logger=Logger.getLogger(UserDetailServiceImpl.class);
        @Autowired
        private IUserService userService;
        @Autowired
        private IRoleService roleService;
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
           logger.info("===========授权============");
    
            User user= null;
            List<Role> role=null;
            try {
                user = userService.findUserByUsername(username);
                role=roleService.listRoleByUserId(user.getId());
                logger.info("用户角色为:"+role);
            } catch (BaseException e) {
                e.printStackTrace();
            }
            List<GrantedAuthority> list= new ArrayList<GrantedAuthority>();
            list.add(new SimpleGrantedAuthority("ROLE_"+role));
            org.springframework.security.core.userdetails.User authUser = new
                        org.springframework.security.core.userdetails.User
                        (user.getUsername(),user.getPassword(),list);
    
                return authUser;
        }
    }

      该配置将安全级别细分到角色。重写的方法传来的参数为登录的username,再通过该参数从数据库中获取用户,以及相对应的权限,最终通过 将用户、密码、权限传入并实例化org.springframework.security.core.userdetails.User ,从而授权结束。配置安全路径或者方法中的权限依据上述方法中获取并绑定的权限。至此我们就可以对路径进行安全权限保护了。

      转载请注明出处:http://www.cnblogs.com/xxzhuang/p/5960001.html  多谢合作。

  • 相关阅读:
    Fiddler给手机设置代理并抓取https链接
    速盘下载
    多版本firefox共存
    firefox45版本与seleniumIDE
    Linux基础快捷键
    解决虚拟机centOs不能上网问题
    HDU 4893 Wow! Such Sequence!(线段树)
    UVALive 7045 Last Defence
    POJ 3544 Journey with Pigs
    POJ 2499 Binary Tree
  • 原文地址:https://www.cnblogs.com/xxzhuang/p/5960001.html
Copyright © 2011-2022 走看看