security 订阅
网络安全技术及其协议,包括了网络通信安全、信息在网络传输中的保密性和完整性、控制访问受限网域与敏感信息以及在公共网络如因特网上使用隐秘通讯。为了解决这些问题,各大组织及技术供应商纷纷推出了各种网络和信息安全技术。 展开全文
网络安全技术及其协议,包括了网络通信安全、信息在网络传输中的保密性和完整性、控制访问受限网域与敏感信息以及在公共网络如因特网上使用隐秘通讯。为了解决这些问题,各大组织及技术供应商纷纷推出了各种网络和信息安全技术。
信息
外文名
Security
包括了
网络通信安全
中文名
网络安全技术及其协议
推出了
各种网络和信息安全技术
Security基本介绍
Security:网络安全技术及其协议(Network Security Technologies and Protocols:AAA,VPN and Firewall)
收起全文
精华内容
参与话题
问答
  • spring security CSRF防护

    万次阅读 多人点赞 2019-07-31 19:14:30
    从Spring Security 4.0开始,默认情况下会启用CSRF保护,以防止CSRF攻击应用程序,Spring Security CSRF会针对PATCH,POST,PUT和DELETE方法进行防护。 我这边是spring boot项目,在启用了@EnableWebSecurity...

    CSRF是指跨站请求伪造(Cross-site request forgery),是web常见的攻击之一。
    从Spring Security 4.0开始,默认情况下会启用CSRF保护,以防止CSRF攻击应用程序,Spring Security CSRF会针对PATCH,POST,PUT和DELETE方法进行防护。
    我这边是spring boot项目,在启用了@EnableWebSecurity注解后,csrf保护就自动生效了。
    所以在默认配置下,即便已经登录了,页面中发起PATCH,POST,PUT和DELETE请求依然会被拒绝,并返回403,需要在请求接口的时候加入csrfToken才行。
    如果你使用了freemarker之类的模板引擎或者jsp,针对表单提交,可以在表单中增加如下隐藏域:

    <input  type = “hidden”  name = “${_csrf.parameterName}”  value = “${_csrf.token}” /> 
    

    如果您使用的是JSON,则无法在HTTP参数中提交CSRF令牌。相反,您可以在HTTP头中提交令牌。一个典型的模式是将CSRF令牌包含在元标记中。下面显示了一个JSP示例:

    <html> 
    <head> 
    	<meta  name = “_csrf” content = “${_csrf.token}” /> 
    	<!-- 默认标题名称是X-CSRF-TOKEN  --> 
    	<meta  name = “_csrf_header”  content = “${_csrf.headerName}” /> 
    </ head> 
    

    然后,您可以将令牌包含在所有Ajax请求中。如果您使用jQuery,可以使用以下方法完成此操作:

    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");
    $.ajax({
    	url:url,
    	type:'POST',
    	async:false,
    	dataType:'json',    //返回的数据格式:json/xml/html/script/jsonp/text
    	beforeSend: function(xhr) {
    		xhr.setRequestHeader(header, token);  //发送请求前将csrfToken设置到请求头中
    	},
    	success:function(data,textStatus,jqXHR){
    	}
    });
    

    如果你不想启用CSRF保护,可以在spring security配置中取消csrf,如下:

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/login").permitAll()
                    .anyRequest().authenticated()
                    .and()
                	...
            http.csrf().disable(); //取消csrf防护
        }
    }
    
    展开全文
  • springSecurity学习笔记

    千次阅读 2019-05-16 16:02:11
    SpringSecurity是为基于Spring的应用程序提供声明式安全保护的安全性框架。SpringSecurity提供了完整的安全性解决方案,它能够在web请求级别和方法调用级别处理身份认证和授权。因为基于spring框架,所以Spring...

     概念   

        SpringSecurity是为基于Spring的应用程序提供声明式安全保护的安全性框架。SpringSecurity提供了完整的安全性解决方案,它能够在web请求级别和方法调用级别处理身份认证和授权。因为基于spring框架,所以SpringSecurity充分利用了依赖注入和面向切面的技术。

    SpringSecurity从两个角度解决来解决安全问题 

         1  使用Servlet规范中的Filter保护web请求并限制URL级别的访问。

         2 SpringSecurity能够使用SpringAOP保护方法调用——借助于对象代理和使用通知,能够确保只有适当权限的用户才能访问安全保护的方法。

    展开全文
  • spring security——基本介绍(一)

    万次阅读 多人点赞 2019-01-16 10:31:23
    一、spring security 简介 spring security 的核心功能主要包括: 认证 (你是谁) 授权 (你能干什么) 攻击防护 (防止伪造身份) 其核心就是一组过滤器链,项目启动后将会自动配置。最核心的就是 Basic ...

    一、spring security 简介

            spring security 的核心功能主要包括:

    • 认证 (你是谁)
    • 授权 (你能干什么)
    • 攻击防护 (防止伪造身份)

         其核心就是一组过滤器链,项目启动后将会自动配置。最核心的就是 Basic Authentication Filter 用来认证用户的身份,一个在spring security中一种过滤器处理一种认证方式。

    比如,对于username password认证过滤器来说, 

    会检查是否是一个登录请求;

    是否包含username 和 password (也就是该过滤器需要的一些认证信息) ;

    如果不满足则放行给下一个。

         下一个按照自身职责判定是否是自身需要的信息,basic的特征就是在请求头中有 Authorization:Basic eHh4Onh4 的信息。中间可能还有更多的认证过滤器。最后一环是 FilterSecurityInterceptor,这里会判定该请求是否能进行访问rest服务,判断的依据是 BrowserSecurityConfig中的配置,如果被拒绝了就会抛出不同的异常(根据具体的原因)。Exception Translation Filter 会捕获抛出的错误,然后根据不同的认证方式进行信息的返回提示。

    注意:绿色的过滤器可以配置是否生效,其他的都不能控制。

    二、入门项目

         首先创建spring boot项目HelloSecurity,其pom主要依赖如下:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    然后在src/main/resources/templates/目录下创建页面:

    home.html

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
        <head>
            <title>Spring Security Example</title>
        </head>
        <body>
            <h1>Welcome!</h1>
    ​
            <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
        </body>
    </html>

    我们可以看到, 在这个简单的视图中包含了一个链接: “/hello”. 链接到了如下的页面,Thymeleaf模板如下:

    hello.html

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
        <head>
            <title>Hello World!</title>
        </head>
        <body>
            <h1>Hello world!</h1>
        </body>
    </html>

    Web应用程序基于Spring MVC。 因此,你需要配置Spring MVC并设置视图控制器来暴露这些模板。 如下是一个典型的Spring MVC配置类。在src/main/java/hello目录下(所以java都在这里):

    @Configuration
    public class MvcConfig extends WebMvcConfigurerAdapter {
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/home").setViewName("home");
            registry.addViewController("/").setViewName("home");
            registry.addViewController("/hello").setViewName("hello");
            registry.addViewController("/login").setViewName("login");
        }
    }

         addViewControllers()方法(覆盖WebMvcConfigurerAdapter中同名的方法)添加了四个视图控制器。 两个视图控制器引用名称为“home”的视图(在home.html中定义),另一个引用名为“hello”的视图(在hello.html中定义)。 第四个视图控制器引用另一个名为“login”的视图。 将在下一部分中创建该视图。此时,可以跳过来使应用程序可执行并运行应用程序,而无需登录任何内容。然后启动程序如下:

    @SpringBootApplication
    public class Application {
    ​
        public static void main(String[] args) throws Throwable {
            SpringApplication.run(Application.class, args);
        }
    }

    2、加入Spring Security

         假设你希望防止未经授权的用户访问“/ hello”。 此时,如果用户点击主页上的链接,他们会看到问候语,请求被没有被拦截。 你需要添加一个障碍,使得用户在看到该页面之前登录。您可以通过在应用程序中配置Spring Security来实现。 如果Spring Security在类路径上,则Spring Boot会使用“Basic认证”来自动保护所有HTTP端点。 同时,你可以进一步自定义安全设置。首先在pom文件中引入:

    <dependencies>
        ...
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
        ...
    </dependencies>

    如下是安全配置,使得只有认证过的用户才可以访问到问候页面:

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                    .antMatchers("/", "/home").permitAll()
                    .anyRequest().authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll()
                    .and()
                .logout()
                    .permitAll();
        }
    ​
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth
                .inMemoryAuthentication()
                    .withUser("user").password("password").roles("USER");
        }
    }

         WebSecurityConfig类使用了@EnableWebSecurity注解 ,以启用Spring Security的Web安全支持,并提供Spring MVC集成。它还扩展了WebSecurityConfigurerAdapter,并覆盖了一些方法来设置Web安全配置的一些细节。

         configure(HttpSecurity)方法定义了哪些URL路径应该被保护,哪些不应该。具体来说,“/”和“/ home”路径被配置为不需要任何身份验证。所有其他路径必须经过身份验证。

         当用户成功登录时,它们将被重定向到先前请求的需要身份认证的页面。有一个由 loginPage()指定的自定义“/登录”页面,每个人都可以查看它。

         对于configureGlobal(AuthenticationManagerBuilder) 方法,它将单个用户设置在内存中。该用户的用户名为“user”,密码为“password”,角色为“USER”。

         现在我们需要创建登录页面。前面我们已经配置了“login”的视图控制器,因此现在只需要创建登录页面即可:

    login.html

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
        <head>
            <title>Spring Security Example </title>
        </head>
        <body>
            <div th:if="${param.error}">
                Invalid username and password.
            </div>
            <div th:if="${param.logout}">
                You have been logged out.
            </div>
            <form th:action="@{/login}" method="post">
                <div><label> User Name : <input type="text" name="username"/> </label></div>
                <div><label> Password: <input type="password" name="password"/> </label></div>
                <div><input type="submit" value="Sign In"/></div>
            </form>
        </body>
    </html>

         你可以看到,这个Thymeleaf模板只是提供一个表单来获取用户名和密码,并将它们提交到“/ login”。 根据配置,Spring Security提供了一个拦截该请求并验证用户的过滤器。 如果用户未通过认证,该页面将重定向到“/ login?error”,并在页面显示相应的错误消息。 注销成功后,我们的应用程序将发送到“/ login?logout”,我们的页面显示相应的登出成功消息。最后,我们需要向用户提供一个显示当前用户名和登出的方法。 更新hello.html 向当前用户打印一句hello,并包含一个“注销”表单,如下所示:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
        <head>
            <title>Hello World!</title>
        </head>
        <body>
            <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
            <form th:action="@{/logout}" method="post">
                <input type="submit" value="Sign Out"/>
            </form>
        </body>
    </html>

    三、参数详解

    1、注解 @EnableWebSecurity

         在 Spring boot 应用中使用 Spring Security,用到了 @EnableWebSecurity注解,官方说明为,该注解和 @Configuration 注解一起使用, 注解 WebSecurityConfigurer 类型的类,或者利用@EnableWebSecurity 注解继承 WebSecurityConfigurerAdapter的类,这样就构成了 Spring Security 的配置。

    2、抽象类 WebSecurityConfigurerAdapter

         一般情况,会选择继承 WebSecurityConfigurerAdapter 类,其官方说明为:WebSecurityConfigurerAdapter 提供了一种便利的方式去创建 WebSecurityConfigurer的实例,只需要重写 WebSecurityConfigurerAdapter 的方法,即可配置拦截什么URL、设置什么权限等安全控制。

    3、方法 configure(AuthenticationManagerBuilder auth) 和 configure(HttpSecurity http)

         Demo 中重写了 WebSecurityConfigurerAdapter 的两个方法:

       /**
         * 通过 {@link #authenticationManager()} 方法的默认实现尝试获取一个 {@link AuthenticationManager}.
         * 如果被复写, 应该使用{@link AuthenticationManagerBuilder} 来指定 {@link AuthenticationManager}.
         *
         * 例如, 可以使用以下配置在内存中进行注册公开内存的身份验证{@link UserDetailsService}:
         *
         * // 在内存中添加 user 和 admin 用户
         * @Override
         * protected void configure(AuthenticationManagerBuilder auth) {
         *     auth
         *       .inMemoryAuthentication().withUser("user").password("password").roles("USER").and()
         *         .withUser("admin").password("password").roles("USER", "ADMIN");
         * }
         *
         * // 将 UserDetailsService 显示为 Bean
         * @Bean
         * @Override
         * public UserDetailsService userDetailsServiceBean() throws Exception {
         *     return super.userDetailsServiceBean();
         * }
         *
         */
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            this.disableLocalConfigureAuthenticationBldr = true;
        }
    
    
        /**
         * 复写这个方法来配置 {@link HttpSecurity}. 
         * 通常,子类不能通过调用 super 来调用此方法,因为它可能会覆盖其配置。 默认配置为:
         * 
         * http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
         *
         */
        protected void configure(HttpSecurity http) throws Exception {
            logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");
    ​
            http
                .authorizeRequests()
                    .anyRequest().authenticated()
                    .and()
                .formLogin().and()
                .httpBasic();
        }

    4、final 类 HttpSecurity

    HttpSecurity 常用方法及说明:

    方法 说明
    openidLogin() 用于基于 OpenId 的验证
    headers() 将安全标头添加到响应
    cors() 配置跨域资源共享( CORS )
    sessionManagement() 允许配置会话管理
    portMapper() 允许配置一个PortMapper(HttpSecurity#(getSharedObject(class))),其他提供SecurityConfigurer的对象使用 PortMapper 从 HTTP 重定向到 HTTPS 或者从 HTTPS 重定向到 HTTP。默认情况下,Spring Security使用一个PortMapperImpl映射 HTTP 端口8080到 HTTPS 端口8443,HTTP 端口80到 HTTPS 端口443
    jee() 配置基于容器的预认证。 在这种情况下,认证由Servlet容器管理
    x509() 配置基于x509的认证
    rememberMe 允许配置“记住我”的验证
    authorizeRequests() 允许基于使用HttpServletRequest限制访问
    requestCache() 允许配置请求缓存
    exceptionHandling() 允许配置错误处理
    securityContext() HttpServletRequests之间的SecurityContextHolder上设置SecurityContext的管理。 当使用WebSecurityConfigurerAdapter时,这将自动应用
    servletApi() HttpServletRequest方法与在其上找到的值集成到SecurityContext中。 当使用WebSecurityConfigurerAdapter时,这将自动应用
    csrf() 添加 CSRF 支持,使用WebSecurityConfigurerAdapter时,默认启用
    logout() 添加退出登录支持。当使用WebSecurityConfigurerAdapter时,这将自动应用。默认情况是,访问URL”/ logout”,使HTTP Session无效来清除用户,清除已配置的任何#rememberMe()身份验证,清除SecurityContextHolder,然后重定向到”/login?success”
    anonymous() 允许配置匿名用户的表示方法。 当与WebSecurityConfigurerAdapter结合使用时,这将自动应用。 默认情况下,匿名用户将使用org.springframework.security.authentication.AnonymousAuthenticationToken表示,并包含角色 “ROLE_ANONYMOUS”
    formLogin() 指定支持基于表单的身份验证。如果未指定FormLoginConfigurer#loginPage(String),则将生成默认登录页面
    oauth2Login() 根据外部OAuth 2.0或OpenID Connect 1.0提供程序配置身份验证
    requiresChannel() 配置通道安全。为了使该配置有用,必须提供至少一个到所需信道的映射
    httpBasic() 配置 Http Basic 验证
    addFilterAt() 在指定的Filter类的位置添加过滤器

    5、类 AuthenticationManagerBuilder

    /**
    * {@link SecurityBuilder} used to create an {@link AuthenticationManager}. Allows for
    * easily building in memory authentication, LDAP authentication, JDBC based
    * authentication, adding {@link UserDetailsService}, and adding
    * {@link AuthenticationProvider}'s.
    */

            意思是,AuthenticationManagerBuilder 用于创建一个 AuthenticationManager,让我能够轻松的实现内存验证、LADP验证、基于JDBC的验证、添加UserDetailsService、添加AuthenticationProvider。

    四、原理讲解

    1、校验流程图

     

    2、源码分析

    • AbstractAuthenticationProcessingFilter 抽象类
        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
                throws IOException, ServletException {
    ​
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;
    ​
            if (!requiresAuthentication(request, response)) {
                chain.doFilter(request, response);
    ​
                return;
            }
    ​
            if (logger.isDebugEnabled()) {
                logger.debug("Request is to process authentication");
            }
    ​
            Authentication authResult;
    ​
            try {
                authResult = attemptAuthentication(request, response);
                if (authResult == null) {
                    // return immediately as subclass has indicated that it hasn't completed
                    // authentication
                    return;
                }
                sessionStrategy.onAuthentication(authResult, request, response);
            }
            catch (InternalAuthenticationServiceException failed) {
                logger.error(
                        "An internal error occurred while trying to authenticate the user.",
                        failed);
                unsuccessfulAuthentication(request, response, failed);
    ​
                return;
            }
            catch (AuthenticationException failed) {
                // Authentication failed
                unsuccessfulAuthentication(request, response, failed);
    ​
                return;
            }
    ​
            // Authentication success
            if (continueChainBeforeSuccessfulAuthentication) {
                chain.doFilter(request, response);
            }
    ​
            successfulAuthentication(request, response, chain, authResult);
        }

            调用 requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。如果需要验证,则会调用 attemptAuthentication(HttpServletRequest, HttpServletResponse) 方法,有三种结果:

    1. 返回一个 Authentication 对象。配置的 SessionAuthenticationStrategy` 将被调用,然后 然后调用 successfulAuthentication(HttpServletRequest,HttpServletResponse,FilterChain,Authentication) 方法。
    2. 验证时发生 AuthenticationException。unsuccessfulAuthentication(HttpServletRequest, HttpServletResponse, AuthenticationException) 方法将被调用。
    3. 返回Null,表示身份验证不完整。假设子类做了一些必要的工作(如重定向)来继续处理验证,方法将立即返回。假设后一个请求将被这种方法接收,其中返回的Authentication对象不为空。
    • UsernamePasswordAuthenticationFilter(AbstractAuthenticationProcessingFilter的子类)
    public Authentication attemptAuthentication(HttpServletRequest request,
                HttpServletResponse response) throws AuthenticationException {
            if (postOnly && !request.getMethod().equals("POST")) {
                throw new AuthenticationServiceException(
                        "Authentication method not supported: " + request.getMethod());
            }
    ​
            String username = obtainUsername(request);
            String password = obtainPassword(request);
    ​
            if (username == null) {
                username = "";
            }
    ​
            if (password == null) {
                password = "";
            }
    ​
            username = username.trim();
    ​
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                    username, password);
    ​
            // Allow subclasses to set the "details" property
            setDetails(request, authRequest);
    ​
            return this.getAuthenticationManager().authenticate(authRequest);
        }

            attemptAuthentication () 方法将 request 中的 username 和 password 生成 UsernamePasswordAuthenticationToken 对象,用于 AuthenticationManager 的验证(即 this.getAuthenticationManager().authenticate(authRequest) )。默认情况下注入 Spring 容器的 AuthenticationManager 是 ProviderManager。

    • ProviderManager(AuthenticationManager的实现类)
    public Authentication authenticate(Authentication authentication)
        throws AuthenticationException {
        Class<? extends Authentication> toTest = authentication.getClass();
        AuthenticationException lastException = null;
        Authentication result = null;
        boolean debug = logger.isDebugEnabled();
    ​
        for (AuthenticationProvider provider : getProviders()) {
            if (!provider.supports(toTest)) {
                continue;
            }
    ​
            if (debug) {
                logger.debug("Authentication attempt using "
                             + provider.getClass().getName());
            }
    ​
            try {
                result = provider.authenticate(authentication);
    ​
                if (result != null) {
                    copyDetails(authentication, result);
                    break;
                }
            }
            catch (AccountStatusException e) {
                prepareException(e, authentication);
                // SEC-546: Avoid polling additional providers if auth failure is due to
                // invalid account status
                throw e;
            }
            catch (InternalAuthenticationServiceException e) {
                prepareException(e, authentication);
                throw e;
            }
            catch (AuthenticationException e) {
                lastException = e;
            }
        }
    ​
        if (result == null && parent != null) {
            // Allow the parent to try.
            try {
                result = parent.authenticate(authentication);
            }
            catch (ProviderNotFoundException e) {
                // ignore as we will throw below if no other exception occurred prior to
                // calling parent and the parent
                // may throw ProviderNotFound even though a provider in the child already
                // handled the request
            }
            catch (AuthenticationException e) {
                lastException = e;
            }
        }
    ​
        if (result != null) {
            if (eraseCredentialsAfterAuthentication
                && (result instanceof CredentialsContainer)) {
                // Authentication is complete. Remove credentials and other secret data
                // from authentication
                ((CredentialsContainer) result).eraseCredentials();
            }
    ​
            eventPublisher.publishAuthenticationSuccess(result);
            return result;
        }
    ​
        // Parent was null, or didn't authenticate (or throw an exception).
    ​
        if (lastException == null) {
            lastException = new ProviderNotFoundException(messages.getMessage(
                "ProviderManager.providerNotFound",
                new Object[] { toTest.getName() },
                "No AuthenticationProvider found for {0}"));
        }
    ​
        prepareException(lastException, authentication);
    ​
        throw lastException;
    }

            尝试验证 Authentication 对象。AuthenticationProvider 列表将被连续尝试,直到 AuthenticationProvider 表示它能够认证传递的过来的Authentication 对象。然后将使用该 AuthenticationProvider 尝试身份验证。如果有多个 AuthenticationProvider 支持验证传递过来的Authentication 对象,那么由第一个来确定结果,覆盖早期支持AuthenticationProviders 所引发的任何可能的AuthenticationException。 成功验证后,将不会尝试后续的AuthenticationProvider。如果最后所有的 AuthenticationProviders 都没有成功验证 Authentication 对象,将抛出 AuthenticationException。从代码中不难看出,由 provider 来验证 authentication, 核心点方法是:

    Authentication result = provider.authenticate(authentication);

    此处的 provider 是 AbstractUserDetailsAuthenticationProvider,AbstractUserDetailsAuthenticationProvider 是AuthenticationProvider的实现,看看它的 authenticate(authentication) 方法:

    // 验证 authentication
    public Authentication authenticate(Authentication authentication)
                throws AuthenticationException {
            Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
                    messages.getMessage(
                            "AbstractUserDetailsAuthenticationProvider.onlySupports",
                            "Only UsernamePasswordAuthenticationToken is supported"));
    ​
            // Determine username
            String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED"
                    : authentication.getName();
    ​
            boolean cacheWasUsed = true;
            UserDetails user = this.userCache.getUserFromCache(username);
    ​
            if (user == null) {
                cacheWasUsed = false;
    ​
                try {
                    user = retrieveUser(username,
                            (UsernamePasswordAuthenticationToken) authentication);
                }
                catch (UsernameNotFoundException notFound) {
                    logger.debug("User '" + username + "' not found");
    ​
                    if (hideUserNotFoundExceptions) {
                        throw new BadCredentialsException(messages.getMessage(
                                "AbstractUserDetailsAuthenticationProvider.badCredentials",
                                "Bad credentials"));
                    }
                    else {
                        throw notFound;
                    }
                }
    ​
                Assert.notNull(user,
                        "retrieveUser returned null - a violation of the interface contract");
            }
    ​
            try {
                preAuthenticationChecks.check(user);
                additionalAuthenticationChecks(user,
                        (UsernamePasswordAuthenticationToken) authentication);
            }
            catch (AuthenticationException exception) {
                if (cacheWasUsed) {
                    // There was a problem, so try again after checking
                    // we're using latest data (i.e. not from the cache)
                    cacheWasUsed = false;
                    user = retrieveUser(username,
                            (UsernamePasswordAuthenticationToken) authentication);
                    preAuthenticationChecks.check(user);
                    additionalAuthenticationChecks(user,
                            (UsernamePasswordAuthenticationToken) authentication);
                }
                else {
                    throw exception;
                }
            }
    ​
            postAuthenticationChecks.check(user);
    ​
            if (!cacheWasUsed) {
                this.userCache.putUserInCache(user);
            }
    ​
            Object principalToReturn = user;
    ​
            if (forcePrincipalAsString) {
                principalToReturn = user.getUsername();
            }
    ​
            return createSuccessAuthentication(principalToReturn, authentication, user);
        }

    AbstractUserDetailsAuthenticationProvider 内置了缓存机制,从缓存中获取不到的 UserDetails 信息的话,就调用如下方法获取用户信息,然后和 用户传来的信息进行对比来判断是否验证成功。

    // 获取用户信息
    UserDetails user = retrieveUser(username,
     (UsernamePasswordAuthenticationToken) authentication);

    retrieveUser() 方法在 DaoAuthenticationProvider 中实现,DaoAuthenticationProvider 是 AbstractUserDetailsAuthenticationProvider的子类。具体实现如下:

    protected final UserDetails retrieveUser(String username,
                UsernamePasswordAuthenticationToken authentication)
                throws AuthenticationException {
            UserDetails loadedUser;
    ​
            try {
                loadedUser = this.getUserDetailsService().loadUserByUsername(username);
            }
            catch (UsernameNotFoundException notFound) {
                if (authentication.getCredentials() != null) {
                    String presentedPassword = authentication.getCredentials().toString();
                    passwordEncoder.isPasswordValid(userNotFoundEncodedPassword,
                            presentedPassword, null);
                }
                throw notFound;
            }
            catch (Exception repositoryProblem) {
                throw new InternalAuthenticationServiceException(
                        repositoryProblem.getMessage(), repositoryProblem);
            }
    ​
            if (loadedUser == null) {
                throw new InternalAuthenticationServiceException(
                        "UserDetailsService returned null, which is an interface contract violation");
            }
            return loadedUser;
        }

    可以看到此处的返回对象 userDetails 是由 UserDetailsService 的 #loadUserByUsername(username) 来获取的。

    展开全文
  • 在Spring Boot中使用Spring Security实现权限控制

    万次阅读 多人点赞 2017-01-12 15:52:37
    Spring Boot框架我们前面已经介绍了很多了,相信看了前面的博客的小伙伴对Spring Boot...OK,那我们今天要说的是Spring Boot中另外一个比较重要的东西,那就是Spring Security,这是一个专门针对基于Spring的项目的安全

    关注公众号【江南一点雨】,专注于 Spring Boot+微服务以及前后端分离等全栈技术,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!


    Spring Boot框架我们前面已经介绍了很多了,相信看了前面的博客的小伙伴对Spring Boot应该有一个大致的了解了吧,如果有小伙伴对Spring Boot尚不熟悉,可以先移步这里从SpringMVC到Spring Boot,老司机请略过。OK,那我们今天要说的是Spring Boot中另外一个比较重要的东西,那就是Spring Security,这是一个专门针对基于Spring的项目的安全框架,它主要是利用了我们前文介绍过的的AOP(Spring基础配置)来实现的。以前在Spring框架中使用Spring Security需要我们进行大量的XML配置,但是,Spring Boot在这里依然有惊喜带给我们,我们今天就一起来看看。
    毫无疑问,Spring Boot针对Spring Security也提供了自动配置的功能,这些默认的自动配置极大的简化了我们的开发工作,我们今天就来看看这个吧。
    #创建Project并添加相关依赖
    Project的创建和前文一样,唯一要注意的地方就是创建的时候添加的依赖不同,如下图:
    这里写图片描述
    OK,创建成功之后添加相关依赖,数据库我这里使用MySql,所以添加MySql驱动,然后要添加Spring Security的支持,所以还要添加Spring Security的依赖,如下:

    <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity4</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.40</version>
            </dependency>
    

    #配置application.properties
    这个东东的配置还是和我们上文说到的是一样的,这里也没啥好说的,有问题的小伙伴翻看前文(初识在Spring Boot中使用JPA):

    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/sang?useUnicode=true&characterEncoding=utf-8
    spring.datasource.username=root
    spring.datasource.password=sang
    logging.level.org.springframework.security=info
    spring.thymeleaf.cache=false
    spring.jpa.hibernate.ddl-auto=update
    spring.jpa.show-sql=true
    

    #定义用户和角色
    我们这里使用JPA来定义用户和角色,用户和角色都存储在数据库中,我们直接通过在数据库中查询然后来使用。

    定义角色

    我们的角色实体类和表都很简单,就两个字段,一个id,一个name属性表示角色的名称,实体类如下;

    @Entity
    public class SysRole {
        @Id
        @GeneratedValue
        private Long id;
        private String name;
    
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    

    OK,简简单单就这两个属性。
    ##定义用户
    我们在定义用户的时候需要实现UserDetails接口,这样我们的用户实体即为Spring Security所使用的用户,定义好用户之后,我们还要配置用户和角色之间的多对多关系,正常情况下,角色和权限是两回事,所以我们还需要重写getAuthorities方法,将用户的角色和权限关联起来,代码如下:

    @Entity
    public class SysUser implements UserDetails {
        @Id
        @GeneratedValue
        private Long id;
        private String username;
        private String password;
    
        @ManyToMany(cascade = {CascadeType.REFRESH},fetch = FetchType.EAGER)
        private List<SysRole> roles;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public List<SysRole> getRoles() {
            return roles;
        }
    
        public void setRoles(List<SysRole> roles) {
            this.roles = roles;
        }
    
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            List<GrantedAuthority> auths = new ArrayList<>();
            List<SysRole> roles = this.getRoles();
            for (SysRole role : roles) {
                auths.add(new SimpleGrantedAuthority(role.getName()));
            }
            return auths;
        }
    
        @Override
        public String getPassword() {
            return this.password;
        }
    
        @Override
        public String getUsername() {
            return this.username;
        }
    
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
    
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
    
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        @Override
        public boolean isEnabled() {
            return true;
        }
    }
    
    

    OK,经过上面两个步骤之后我们的用户就和角色关联起来了,这个时候运行Project就会在数据库中自动帮我们生成三张表,用户表、角色表和两者的关联表,如下:
    这里写图片描述
    ##预设数据
    我们先在表中定义好几个角色和用户,方便我们后边做测试用,OK,预设数据的话,那我们执行如下几行数据插入代码:

    insert  into `sys_role`(`id`,`name`) values (1,'ROLE_ADMIN'),(2,'ROLE_USER');
    
    insert  into `sys_user`(`id`,`password`,`username`) values (1,'root','root'),(2,'sang','sang');
    
    insert  into `sys_user_roles`(`sys_user_id`,`roles_id`) values (1,1),(2,2);
    
    

    我们向数据库中插入两个用户两个角色,再将这两个用户两个角色关联起来即可。
    #创建传值对象
    数据创建成功之后,在客户端请求网页的时候我们需要有一个实体类用来向客户端传递消息,OK,那我们创建一个MSG对象:

    public class Msg {
        private String title;
        private String content;
        private String extraInfo;
    
        public Msg() {
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        public String getExtraInfo() {
            return extraInfo;
        }
    
        public void setExtraInfo(String extraInfo) {
            this.extraInfo = extraInfo;
        }
    
        public Msg(String title, String content, String extraInfo) {
            this.title = title;
            this.content = content;
            this.extraInfo = extraInfo;
        }
    }
    

    这就是一个普通的类,没什么好说的。
    #创建数据访问接口

    public interface SysUserRepository extends JpaRepository<SysUser, Long> {
        SysUser findByUsername(String username);
    }
    

    这个也是写了n多遍的东西了,不赘述,关于这里如果小伙伴有疑问可以参考这里(初识在Spring Boot中使用JPA)。需要注意的是这里只需要一个根据用户名查询出用户的方法即可,不需要通过用户名和密码去查询。
    #自定义UserDetailsService
    自定义UserDetailsService,实现相应的接口,如下:

    public class CustomUserService implements UserDetailsService {
        @Autowired
        SysUserRepository userRepository;
        @Override
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
            SysUser user = userRepository.findByUsername(s);
            if (user == null) {
                throw new UsernameNotFoundException("用户名不存在");
            }
            System.out.println("s:"+s);
            System.out.println("username:"+user.getUsername()+";password:"+user.getPassword());
            return user;
        }
    }
    

    首先这里我们需要重写UserDetailsService接口,然后实现该接口中的loadUserByUsername方法,通过该方法查询到对应的用户,这里之所以要实现UserDetailsService接口,是因为在Spring Security中我们配置相关参数需要UserDetailsService类型的数据。
    #SpringMVC配置

    @Configuration
    public class WebMvcConfig extends WebMvcConfigurerAdapter {
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/login").setViewName("login");
        }
    }
    

    当用户访问login时跳转到login.html页面。
    #配置Spring Security

    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Bean
        UserDetailsService customUserService() {
            return new CustomUserService();
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(customUserService());
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .anyRequest().authenticated()
                    .and().formLogin().loginPage("/login").failureUrl("/login?error").permitAll().and()
                    .logout().permitAll();
        }
    }
    

    OK ,关于这个配置我要多说两句:

    1.首先当我们要自定义Spring Security的时候我们需要继承自WebSecurityConfigurerAdapter来完成,相关配置重写对应 方法即可。
    2.我们在这里注册CustomUserService的Bean,然后通过重写configure方法添加我们自定义的认证方式。
    3.在configure(HttpSecurity http)方法中,我们设置了登录页面,而且登录页面任何人都可以访问,然后设置了登录失败地址,也设置了注销请求,注销请求也是任何人都可以访问的。
    4.permitAll表示该请求任何人都可以访问,.anyRequest().authenticated(),表示其他的请求都必须要有权限认证。
    5.这里我们可以通过匹配器来匹配路径,比如antMatchers方法,假设我要管理员才可以访问admin文件夹下的内容,我可以这样来写:.antMatchers("/admin/**").hasRole("ROLE_ADMIN"),也可以设置admin文件夹下的文件可以有多个角色来访问,写法如下:.antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN","ROLE_USER")
    6.可以通过hasIpAddress来指定某一个ip可以访问该资源,假设只允许访问ip为210.210.210.210的请求获取admin下的资源,写法如下.antMatchers("/admin/**").hasIpAddress("210.210.210.210")
    7.更多的权限控制方式参看下表:
    这里写图片描述
    8.这里我们还可以做更多的配置,参考如下代码:

    http.authorizeRequests()
                    .anyRequest().authenticated()
                    .and().formLogin().loginPage("/login")
                    //设置默认登录成功跳转页面
                    .defaultSuccessUrl("/index").failureUrl("/login?error").permitAll()
                    .and()
                    //开启cookie保存用户数据
                    .rememberMe()
                    //设置cookie有效期
                    .tokenValiditySeconds(60 * 60 * 24 * 7)
                    //设置cookie的私钥
                    .key("")
                    .and()
                    .logout()
                    //默认注销行为为logout,可以通过下面的方式来修改
                    .logoutUrl("/custom-logout")
                    //设置注销成功后跳转页面,默认是跳转到登录页面
                    .logoutSuccessUrl("")
                    .permitAll();
    

    OK,这里算是核心了,多说两句。

    #创建登录页面

    在template文件夹中创建login.html页面,内容如下:

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8"/>
        <title>登录</title>
        <link rel="stylesheet" th:href="@{css/bootstrap.min.css}"/>
        <link rel="stylesheet" th:href="@{css/signin.css}"/>
        <style type="text/css">
            body {
                padding-top: 50px;
            }
    
            .starter-template {
                padding: 40px 15px;
                text-align: center;
            }
        </style>
    </head>
    <body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <a class="navbar-brand" href="#">Spring Security演示</a>
            </div>
            <div id="navbar" class="collapse navbar-collapse">
                <ul class="nav navbar-nav">
                    <li><a th:href="@{/}">首页</a></li>
                    <li><a th:href="@{http://www.baidu.com}">百度</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <div class="container">
        <div class="starter-template">
            <p th:if="${param.logout}" class="bg-warning">已注销</p>
            <p th:if="${param.error}" class="bg-danger">有错误,请重试</p>
            <h2>使用账号密码登录</h2>
            <form class="form-signin" role="form" name="form" th:action="@{/login}" action="/login" method="post">
                <div class="form-group">
                    <label for="username">账号</label>
                    <input type="text" class="form-control" name="username" value="" placeholder="账号"/>
                </div>
                <div class="form-group">
                    <label for="password">密码</label>
                    <input type="password" class="form-control" name="password" placeholder="密码"/>
                </div>
                <input type="submit" id="login" value="Login" class="btn btn-primary"/>
            </form>
        </div>
    </div>
    </body>
    </html>
    

    这里就是一个普通的html页面,用到了thymeleaf模板引擎(thymeleaf可以参考这两篇文章使用Spring Boot开发Web项目/使用Spring Boot开发Web项目(二)之添加HTTPS支持),
    #创建登录成功后跳转页面

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org"
          xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
    <head>
        <meta charset="UTF-8"/>
        <title sec:authentication="name"></title>
        <link rel="stylesheet" th:href="@{css/bootstrap.min.css}"/>
        <style type="text/css">
            body {
                padding-top: 50px;
            }
    
            .starter-template {
                padding: 40px 15px;
                text-align: center;
            }
        </style>
    </head>
    <body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <a class="navbar-brand" href="#">Spring Security演示</a>
            </div>
            <div id="navbar" class="collapse navbar-collapse">
                <ul class="nav navbar-nav">
                    <li><a th:href="@{/}">首页</a></li>
                    <li><a th:href="@{http://www.baidu.com}">百度</a></li>
                </ul>
            </div>
        </div>
    </nav>
    <div class="container">
        <div class="starter-template">
            <h1 th:text="${msg.title}"></h1>
            <p class="bg-primary" th:text="${msg.content}"></p>
            <div sec:authorize="hasRole('ROLE_ADMIN')">
                <p class="bg-info" th:text="${msg.extraInfo}"></p>
            </div>
            <div sec:authorize="hasRole('ROLE_USER')">
                <p class="bg-info">无更多显示信息</p>
            </div>
            <form th:action="@{/logout}" method="post">
                <input type="submit" class="btn btn-primary" value="注销"/>
            </form>
        </div>
    </div>
    </body>
    </html>
    

    这里有如下几个问题需要说明:

    1.在html标签中我们引入的Spring Security
    2.通过sec:authentication="name"我们可以获取当前用户名
    3.sec:authorize="hasRole('ROLE_ADMIN')表示当前用户角色为ROLE_ADMIN的话显示里边的内容
    4.sec:authorize="hasRole('ROLE_USER')表示当前用户角色为ROLE_USER的话显示该DIV里边的内容

    #添加控制器

    @Controller
    public class HomeController {
        @RequestMapping("/")
        public String index(Model model) {
            Msg msg = new Msg("测试标题", "测试内容", "额外信息,只对管理员显示");
            model.addAttribute("msg", msg);
            return "index";
        }
    }
    

    #测试

    首页如下:

    访问http://localhost:8080/自动跳转到http://localhost:8080/login
    这里写图片描述
    ##登录出错
    输入错误的账号密码进行登录,结果如下:
    这里写图片描述
    ##管理员登录
    使用管理员帐号密码登录,结果如下:
    这里写图片描述
    ##普通用户登录
    使用普通用户帐号密码登录,结果如下:
    这里写图片描述
    ##注销
    点击注销按钮,结果如下:
    这里写图片描述

    OK,以上就是对Spring Security的一个简单介绍,是不是比自己通过过滤器、拦截器神马的来弄简单多了。

    本文案例下载:
    本文案例GitHub地址https://github.com/lenve/JavaEETest/tree/master/Test26-Security.

    更多Spring Boot资料请移步这里从SpringMVC到Spring Boot

    以上。

    参考资料:
    《JavaEE开发的颠覆者 Spring Boot实战》第九章

    展开全文
  • <security:global-method-security pre-post-annotations="enabled" jsr250-annotations="enabled" secured-annotations="enabled"></security:global-method-security> <!-- 配置不拦截的资源 --> <security...
  • Spring Security 工作原理概览

    万次阅读 多人点赞 2019-04-27 08:02:58
    本文由读者 muggle 投稿,muggle 是一位具备极客精神的90后单身老实猿,对 Spring Security 有丰富的使用经验,muggle 个人博客地址是 h...
  • Spring Security中,安全构建器HttpSecurity和WebSecurity的区别是 : WebSecurity不仅通过HttpSecurity定义某些请求的安全控制,也定义其他某些请求可以忽略安全控制; HttpSecurity仅用于定义需要安全控制的请求; ...
  • at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) at org.springframework.security.web.access.intercept....
  • springboot+security实现权限管理

    万次阅读 多人点赞 2019-03-21 14:06:45
    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,...
  • 十二、SpringBoot 优雅的集成Spring Security

    万次阅读 多人点赞 2019-12-25 11:03:58
    文章目录前言依赖测试简单配置用户和密码application.properties 中配置内存中配置从数据库进行用户认证建库建表pom.xml 增加依赖配置application.propertiesentrymapperRolesMapperRolesMapper....
  • <security:intercept-url pattern="/**" access="ROLE_USER,ROLE_TEST"></security:intercept-url> <!-- login-page 自定义登录页面 login-processing-url 登录页面form表单请求的url地址 default-target-...
  • Spring Boot+Spring Security+JWT 实现 RESTful Api 认证 (一)

    万次阅读 多人点赞 2017-09-13 14:39:51
    摘要:用spring-boot开发RESTful API非常的方便,在生产环境中,对发布的API增加授权保护是非常必要的。现在我们来看如何利用JWT技术为API增加授权保护,保证只有获得授权的用户才能够访问API。...
  • springboot2.1.3 集成springSecurity设置了不需要登入的url无效,全部访问没有登入都跳转到未登入的handler里面。求助哇。 ``` @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity...
  • 作为一个配置HttpSecurity的SecurityConfigurer,ExceptionHandlingConfigurer的配置任务如下 : 配置如下安全过滤器Filter ExceptionTranslationFilter ExceptionHandlingConfigurer配置过程中使用到了如下共享...
  • SpringSecurity超详细入门介绍

    万次阅读 2019-12-02 12:06:54
      权限管理是我们项目中必不可少的一环,实际项目中我们可以自己设计权限管理模块,也可以使用市面上成熟的权限管理框架,比如 shiro或者 SpringSecurity等,前面已经详细的介绍过了 shiro 的使用,本文开始就给...
  • HttpSecurity是Spring Security Config用于配置http请求安全控制的安全构建器(类似于Spring Security XML配置中的http命名空间配置部分),它的构建目标是一...该目标SecurityFilterChain最终会被Spring Security的安...
  • package org.bzxly.yx.security.filter; import org.bzxly.yx.security.entity.Authority; import org.bzxly.yx.security.service.PermissionService; import org.springframework.security.access.ConfigAttribute;...
  • 我现在有一个项目,认证方式是通过springsecurity的,现在需求是做一个微信登录。 关于获取微信用户的信息这部分已经做完了,但是现在有一个问题就是,我们边处理是要求微信用户第一次登录的时候必须绑定手机号码...
  • Security aspects Efficient Deep Learning on Multi-Source Private Data https://arxiv.org/pdf/1807.06689.pdf Chiron: Privacy-preserving Machine Learning as a Service ...
  • SpringBoot集成Spring Security(1)——入门程序

    万次阅读 多人点赞 2018-05-09 09:47:20
    因为项目需要,第一次接触Spring Security,早就听闻Spring Security强大但上手困难,今天学习了一天,翻遍了全网资料,才仅仅出入门道,特整理这篇文章来让后来者少踩一点坑(本文附带实例程序,请放心食用) ...
  • 文章目录一、实现配置多个 HttpSecurity二、实现方法安全...本篇文章不再赘述:学习 Spring Security 看这一篇博客就够了 @Configuration public class MultiHttpSecurityConfig { @Bean PasswordEncoder passwordEn
  • springsecurity3.2 说起来,我这个原本前台是ANGULARJS+HTML写的 但是公司单点登录必须要JSP页面,因为是老系统,html不支持 所以没办法,就写了个JSP来登录 然后我登录上去会报302,而且...
  • 当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异。笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过5-6篇文章,来介绍一下项目中遇到的问题以及我的解决方案,...
  • at ins.framework.security.DBUserDetailsService$AuthoritiesByUsernameMapping.mapRow(DBUserDetailsService.java:134) at org.springframework.jdbc.object.MappingSqlQuery.mapRow(MappingSqlQuery.java:64) ...
  • 配置SpringSecurity报错

    2016-08-19 08:44:07
    Error creating bean with name 'org.springframework.security.filterChains': Cannot resolve reference to bean 'org.springframework.security.web.DefaultSecurityFilterChain#0' while setting bean property ...
  • 使用SpringBoot 2.1.3 +SpringSecurity,按照网上教程设置logoutSuccessUrl为跳转的index路径,但是无法正常跳转,根据查看,页面发起请求/logout随后转向/index,但又被重定向至/login,截图如下 ![图片说明]...
  • 前面我们已经分析了Spring Security的核心过滤器FilterChainProxy的创建和运行过程,认识了建造者和配置器的作用。 现在我们知道WebSecurity作为一个建造者就是用来创建核心过滤器FilterChainProxy实例的。 Web...
  • 使用spring security oauth2框架完成验证授权时,我想添添加一个自定义参数,该怎么实现? --- ![图片说明](https://img-ask.csdn.net/upload/201810/22/1540195338_536644.jpg) * 正常情况下只传递3个值就...
  • Springboot + Spring Security 实现前后端分离登录认证及权限控制前言本文主要的功能文章目录一、数据库表设计建表语句初始化表数据语句二、Spring Security核心配置:WebSecurityConfig三、用户登录认证逻辑:...
  • SpringSecurity授权管理介绍

    千次阅读 2019-12-05 17:07:11
      权限管理的两大核心是:认证和授权,前面我们已经介绍完了认证的内容,本文就给大家来介绍下SpringSecurity的授权管理 一、注解操作   我们在控制器或者service中实现授权操作比较理想的方式就是通过相应的...

空空如也

1 2 3 4 5 ... 20
收藏数 166,413
精华内容 66,565
关键字:

security