重庆分公司,新征程启航

为企业提供网站建设、域名注册、服务器等服务

SpringCloud的spring-security怎么配置

这篇文章主要讲解了“SpringCloud的spring-security怎么配置”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringCloud的spring-security怎么配置”吧!

十多年的绿园网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。成都全网营销的优势是能够根据用户设备显示端的尺寸不同,自动调整绿园建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联从事“绿园网站设计”,“绿园网站推广”以来,每个客户项目都认真落实执行。

一、简介

Web应用的安全管理,主要包括两个方面的内容:身份认证、用户授权,此处使用spring-cloud-security来说明。

二、依赖管理


    org.springframework.cloud
    spring-cloud-starter-security


   org.thymeleaf.extras
   thymeleaf-extras-springsecurity4

三、安全策略配置

Spring Security已经大体实现了,我们这里只是需要一些配置与引用。

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

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

package com.example.demo.config;

 

import com.example.demo.utils.security.CustomUserService;

import com.example.demo.utils.security.LoginSuccessHandler;

import com.example.demo.utils.security.MyFilterSecurityInterceptor;

import com.example.demo.utils.security.SecuritySettings;

import org.apache.commons.lang3.StringUtils;

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.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.builders.WebSecurity;

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;

import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

 

/**

 * Security安全配置

 *

 * @Author: 我爱大金子

 * @Description: Security安全配置

 * @Date: Create in 15:20 2017/7/5

 */

@Configuration

@EnableWebSecurity

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

 

    @Autowired

    private CustomFilterSecurityInterceptor customFilterSecurityInterceptor;    // 权限管理过滤器

    @Autowired

    private SecuritySettings securitySettings;     // 自定义安全配置类

 

    /**注册UserDetailsService的bean*/

    @Bean

    public UserDetailsService customUserService(){

        return new CustomUserService();

    }

 

    /**登录认证*/

    @Override

    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(customUserService()); //userDetailsService验证

 

    }

 

    /***设置不拦截规则*/

    @Override

    public void configure(WebSecurity web) throws Exception {

        web.ignoring().antMatchers("/js/**""/css/**""/images/**""/druid/**");

    }

 

    /**安全策略配置*/

    @Override

    protected void configure(HttpSecurity http) throws Exception {

        // 设置游客可以访问的URI

        if (StringUtils.isNotBlank(securitySettings.getPermitall())) {

            http.authorizeRequests().antMatchers(securitySettings.getPermitall().split(",")).permitAll();

        }

 

        http.authorizeRequests()

                .anyRequest().authenticated() //任何请求,登录后可以访问

                // 配置登录URI、登录失败跳转URI与登录成功后默认跳转URI

                .and().formLogin().loginPage("/login").failureUrl("/login?error").permitAll().defaultSuccessUrl("/"true).successHandler(loginSuccessHandler())

                // 注销行为任意访问

                .and().logout().permitAll()

                // 设置拒绝访问的提示URI

                .and().exceptionHandling().accessDeniedPage("/login?illegal")

        ;

 

        http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);

    }

 

    /**登录成功处理器*/

    private AuthenticationSuccessHandler loginSuccessHandler() {

        return new LoginSuccessHandler();

    }

}

说明:

 loginPage:设置一个实验自定义的登录URI

 loginSuccessHandler:设置自定义的登录处理器

 permitAll:是允许访问

 accessDeniedPage:配置拒绝访问的提示URI

 antMatchers:对URI的配置

了解springcloud架构可以加求求:三五三六二四七二五九

假设我要管理员才可以访问admin文件夹下的内容,如:.antMatchers("/admin/**").hasRole("ROLE_ADMIN"),

也可以设置admin文件夹下的文件可以有多个角色来访问,如:.antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN","ROLE_USER")

也可以通过hasIpAddress来指定某一个ip可以访问该资源,写法如下.antMatchers("/admin/**").hasIpAddress("210.210.210.210") 

3.1、自定义安全配置类 

为是更方便的使用springSecurity,我们自定义一个权限的配置类,如配置登录的URI、游客访问的URI等配置项

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

package com.example.demo.utils.security;

 

import org.springframework.boot.context.properties.ConfigurationProperties;

import org.springframework.context.annotation.Configuration;

 

/**

 * 自定义安全配置类

 *

 * @Author: 我爱大金子

 * @Description: 自定义安全配置类

 * @Date: Create in 9:45 2017/7/6

 */

@Configuration

@ConfigurationProperties(prefix = "securityConfig")

public class SecuritySettings {

    /**允许访问的URL,多个用逗号分隔*/

    private String permitall;

 

    public String getPermitall() {

        return permitall;

    }

 

    public void setPermitall(String permitall) {

        this.permitall = permitall;

    }

}

3.2、登录成功处理器

登录成功后,如果需要对用户的行为做一些记录或者执行其它操作,则可以使用登录成功处理器。

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

package com.example.demo.utils.security;

 

import com.example.demo.pojo.SysUser;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.userdetails.User;

import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

 

/**

 * 登录成功处理器

 *

 * @Author: 我爱大金子

 * @Description: 登录成功处理器

 * @Date: Create in 11:35 2017/7/6

 */

public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Override

    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {

        User userDetails = (User) authentication.getPrincipal();

        System.out.println("登录用户:username=" + userDetails.getUsername() + ", uri=" + request.getContextPath());

        super.onAuthenticationSuccess(request, response, authentication);

    }

}

3.3、springMVC 配置(访问 /login 转向 login.html 页面)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

package com.example.demo.config;

 

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

 

/**

 * springMVC 配置(注册访问 /login 转向 login.html 页面)

 *

 * @Author: 我爱大金子

 * @Description: springMVC 配置(注册访问 /login 转向 login.html 页面)

 * @Date: Create in 16:24 2017/7/5

 */

@Configuration

public class WebMvcConfig extends WebMvcConfigurerAdapter {

 

    @Override

    public void addViewControllers(ViewControllerRegistry registry) {

        registry.addViewController("/login").setViewName("login");

    }

}

四、登录认证

在安全策略配置代码中有,主要看自定义的CustomUserService,此类实现了UserDetailsService接口,重写了loadUserByUsername方法

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

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

package com.example.demo.utils.security;

 

import com.example.demo.dao.SysPermissionDao;

import com.example.demo.dao.SysUserDao;

import com.example.demo.pojo.SysPermission;

import org.springframework.security.core.userdetails.User;

import com.example.demo.pojo.SysUser;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.authority.SimpleGrantedAuthority;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.core.userdetails.UsernameNotFoundException;

 

import java.util.ArrayList;

import java.util.List;

 

/**

 * 自定义UserDetailsService,将用户权限交给springsecurity进行管控

 *

 * @Author: 我爱大金子

 * @Description: 将用户权限交给Springsecurity进行管控

 * @Date: Create in 16:19 2017/7/5

 */

public class CustomUserService implements UserDetailsService {

    @Autowired

    private SysUserDao sysUserDao;

    @Autowired

    private SysPermissionDao sysPermissionDao;

 

    @Override

    public UserDetails loadUserByUsername(String username) {

        SysUser user = sysUserDao.findByUserName(username);

        if (user != null) {

            List permissions = sysPermissionDao.findByAdminUserId(user.getId());

            List grantedAuthorities = new ArrayList <>();

            for (SysPermission permission : permissions) {

                if (permission != null && permission.getName()!=null) {

                    GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName());

                    //1:此处将权限信息添加到 GrantedAuthority 对象中,在后面进行全权限验证时会使用GrantedAuthority 对象。

                    grantedAuthorities.add(grantedAuthority);

                }

            }

            return new User(user.getUsername(), user.getPassword(), grantedAuthorities);

        else {

            throw new UsernameNotFoundException("admin: " + username + " do not exist!");

        }

    }

}

五、权限管理

在Security安全配置类中使用了权限管理过滤器CustomFilterSecurityInterceptor

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

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

package com.example.demo.utils.security;

 

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.security.access.SecurityMetadataSource;

import org.springframework.security.access.intercept.AbstractSecurityInterceptor;

import org.springframework.security.access.intercept.InterceptorStatusToken;

import org.springframework.security.web.FilterInvocation;

import org.springframework.stereotype.Service;

 

import java.io.IOException;

 

/**

 * 权限管理过滤器

 *

 * @Author: 我爱大金子

 * @Description: 权限管理过滤器

 * @Date: Create in 17:16 2017/7/5

 */

@Service

public class CustomFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {

    @Autowired

    private CustomFilterInvocationSecurityMetadataSource customFilterInvocationSecurityMetadataSource;  // 权限配置资源管理器

 

    /**权限管理决断器*/

    @Autowired

    public void setMyAccessDecisionManager(CustomAccessDecisionManager customAccessDecisionManager) {

        super.setAccessDecisionManager(customAccessDecisionManager);

    }

  

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

 

    }

 

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

 

        FilterInvocation fi = new FilterInvocation(request, response, chain);

        invoke(fi);

    }

  

    public void invoke(FilterInvocation fi) throws IOException, ServletException {

        //fi里面有一个被拦截的url

        //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限

        //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够

        InterceptorStatusToken token = super.beforeInvocation(fi);

        try {

            //执行下一个拦截器

            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());

        finally {

            super.afterInvocation(token, null);

        }

    }

 

    @Override

    public void destroy() {

 

    }

 

    @Override

    public Class getSecureObjectClass() {

        return FilterInvocation.class;

    }

 

    @Override

    public SecurityMetadataSource obtainSecurityMetadataSource() {

        return this.customFilterInvocationSecurityMetadataSource;

    }

}

说明:

 customFilterSecurityInterceptor:权限管理过滤器

 customAccessDecisionManager:权限管理决断器

 customFilterInvocationSecurityMetadataSource:权限配置资源管理器

其中过滤器在系统启动时开始工作,并同时导入权限配置资源管理器和权限管理决断器,对用户访问的资源进行管理。权限管理决断器对用户访问的资源与用户拥有的角色权限进行对比,以此来判断用户是否对某个资源具有访问权限。

5.1、权限管理过滤器

继承与AbstractSecurityInterceptor,实时监控用户的行为,防止用户访问未被授权的资源。

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

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

package com.example.demo.utils.security;

 

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.security.access.SecurityMetadataSource;

import org.springframework.security.access.intercept.AbstractSecurityInterceptor;

import org.springframework.security.access.intercept.InterceptorStatusToken;

import org.springframework.security.web.FilterInvocation;

import org.springframework.stereotype.Service;

 

import java.io.IOException;

 

/**

 * 权限管理过滤器

 *

 * @Author: 我爱大金子

 * @Description: 权限管理过滤器

 * @Date: Create in 17:16 2017/7/5

 */

@Service

public class CustomFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {

    Logger log = LoggerFactory.getLogger(CustomFilterSecurityInterceptor.class);

    @Autowired

    private CustomFilterInvocationSecurityMetadataSource customFilterInvocationSecurityMetadataSource;  // 权限配置资源管理器

 

    /**权限管理决断器*/

    @Autowired

    public void setMyAccessDecisionManager(CustomAccessDecisionManager customAccessDecisionManager) {

        super.setAccessDecisionManager(customAccessDecisionManager);

    }

  

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

 

    }

 

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

 

        FilterInvocation fi = new FilterInvocation(request, response, chain);

        log.info("【权限管理过滤器】请求URL:" + fi.getRequestUrl());

        invoke(fi);

    }

  

    public void invoke(FilterInvocation fi) throws IOException, ServletException {

        //fi里面有一个被拦截的url

        //里面调用CustomFilterInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限

        //再调用CustomAccessDecisionManager的decide方法来校验用户的权限是否足够

        InterceptorStatusToken token = super.beforeInvocation(fi);

        try {

            //执行下一个拦截器

            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());

        catch(Exception e) {

            log.error("【权限管理过滤器】【异常】" + e.getMessage(), e);

        finally {

            super.afterInvocation(token, null);

        }

    }

 

    @Override

    public void destroy() {

 

    }

 

    @Override

    public Class getSecureObjectClass() {

        return FilterInvocation.class;

    }

 

    @Override

    public SecurityMetadataSource obtainSecurityMetadataSource() {

        return this.customFilterInvocationSecurityMetadataSource;

    }

}

5.2、权限管理决断器

权限管理的关键部分就是决断器,它实现了AccessDecisionManager,重写了decide方法,使用自定义的决断器,在用户访问受保护的资源时,决断器判断用户拥有的角色中是否对改资源具有访问权限,如果没有,则拒绝访问

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

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

package com.example.demo.utils.security;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.security.access.AccessDecisionManager;

import org.springframework.security.access.AccessDeniedException;

import org.springframework.security.access.ConfigAttribute;

import org.springframework.security.authentication.InsufficientAuthenticationException;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.stereotype.Service;

 

import java.util.Collection;

import java.util.Iterator;

 

/**

 * 权限管理决断器

 *

 * @Author: 我爱大金子

 * @Description: 权限管理决断器

 * @Date: Create in 17:15 2017/7/5

 */

@Service

public class CustomAccessDecisionManager implements AccessDecisionManager {

    Logger log = LoggerFactory.getLogger(CustomAccessDecisionManager.class);

     

    // decide 方法是判定是否拥有权限的决策方法,

    //authentication 是释CustomUserService中循环添加到 GrantedAuthority 对象中的权限信息集合.

    //object 包含客户端发起的请求的requset信息,可转换为 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();

    //configAttributes 为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果,此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。

    @Override

    public void decide(Authentication authentication, Object object, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {

 

        if(null== configAttributes || configAttributes.size() <=0) {

            return;

        }

        ConfigAttribute c;

        String needRole;


文章名称:SpringCloud的spring-security怎么配置
分享URL:http://cqcxhl.cn/article/ppdhhi.html