cas+SpringSecurity注解方式(五)

5.1SpringSecurity搭建
5.1.1 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.itheima</groupId>
    <artifactId>springsecurity-cas-annotation-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!--war包-->
    <packaging>war</packaging>

    <dependencies>
        <!--spring-security-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>

        <!--集成包-->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-cas</artifactId>
            <version>4.2.4.RELEASE</version>
        </dependency>

        <!--cas核心包-->
        <dependency>
            <groupId>org.jasig.cas.client</groupId>
            <artifactId>cas-client-core</artifactId>
            <version>3.3.3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>log4j-over-slf4j</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--日志包-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <!--servlet-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

5.1.2 web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!--指定spring配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring.xml</param-value>
    </context-param>

    <!--spring监听-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--委托过滤器:springSecurityFilterChain-->
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

5.1.3 spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--包扫描-->
    <context:component-scan base-package="org.example" />

</beans>

5.1.4 创建自定义授权认证类

@Component
public class UserDetailsServiceImpl implements UserDetailsService {

    /***
     * 自定义认证授权
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String password="123456";

        //角色信息
        List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
        grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));

        return new User(username,password,grantedAuthorities);
    }
}

5.1.5 创建SpringSecur配置类
配置类需要注意加上@Component、@EnableWebSecurity注解,同时注解3个方法分别为忽略某些地址的安全校验、设置需要拦截过滤的地址的安全校验规则、设置授权认证器三个方法都是configure方法。代码如下:

@Component
@EnableWebSecurity
public class SpringSecurityCOnfig extends WebSecurityConfigurerAdapter {

    /***
     * 三个configure方法
     * 1)忽略某些地址的安全校验
     * 2)设置需要拦截过滤的地址的安全校验规则
     * 3)设置授权认证器
     */


    /***
     * 1)忽略某些地址的安全校验
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/image/**");
        web.ignoring().antMatchers("/403.html");
    }

    /***
     * 2)设置需要拦截过滤的地址的安全校验规则
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //除了上面忽略安全校验的地址,其他的一律需要ROLE_ADMIN角色权限访问
        http.authorizeRequests().anyRequest().access("hasAnyRole('ADMIN')");

        //允许iframe的使用
        http.headers().frameOptions().disable();

        //禁止csrf
        http.csrf().disable();

        //开启登录功能
        http.formLogin();

        //开启登出功能
        http.logout();

        //异常处理
        http.exceptionHandling().accessDeniedPage("/403.html");
    }

    /***
     * 注入自定义授权认证类
     */
    @Autowired
    private UserDetailsService userDetailsService;

    /***
     * 3)设置授权认证器
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }
}
5.1.6 新建资源文件

创建image,并拷贝1.jpg进去,作为开放资源。创建jsp/1.jsp,作为权限控制目录。创建403,作为无权访问的页面。

image.jpg

5.2 集成CAS

5.2.1 创建cas.properties

这里面记录了cas相关的访问地址以及自身相关的访问地址

#CAS服务地址
cas.server.host.url=http://localhost:28083/cas
#CAS服务登录地址
cas.server.host.login_url=http://localhost:28083/cas/login
#CAS服务登出地址
cas.server.host.logout_url=http://localhost:28083/cas/logout?service=http://localhost:28086
#应用访问地址
app.server.host.url=http://localhost:28086
#应用登录地址
app.login.url=/login
#应用登出地址
app.logout.url=/logout

5.2.2 创建CasProperties.java配置类
该类的作用是用于读取上面的配置文件

@Component
public class CasProperties {
    @Value("${cas.server.host.url}")
    private String casServerUrl;

    @Value("${cas.server.host.login_url}")
    private String casServerLoginUrl;

    @Value("${cas.server.host.logout_url}")
    private String casServerLogoutUrl;

    @Value("${app.server.host.url}")
    private String appServerUrl;

    @Value("${app.login.url}")
    private String appLoginUrl;

    @Value("${app.logout.url}")
    private String appLogoutUrl;

    //get...set...
}

5.2.3 集成CAS认证和相关过滤器
修改configure方法,代码如下,分别加入了自定义授权认证类和Cas过滤器以及登出配置。我们需要将之前的用户自定义授权认证类去掉.

/***
 * 2)设置需要拦截过滤的地址的安全校验规则
 * @param http
 * @throws Exception
 */
@Override
protected void configure(HttpSecurity http) throws Exception {
    //除了上面忽略安全校验的地址,其他的一律需要ROLE_ADMIN角色权限访问
    http.authorizeRequests().anyRequest().access("hasAnyRole('ADMIN')");

    //允许iframe的使用
    http.headers().frameOptions().disable();

    //禁止csrf
    http.csrf().disable();

    //开启登录功能
    http.formLogin();

    //开启登出功能
    http.logout();

    //异常处理
    http.exceptionHandling().accessDeniedPage("/403.html")
            .authenticationEntryPoint(casAuthenticationEntryPoint())    //设置自定义授权认证类
            .and()
            .addFilter(casAuthenticationFilter())                       //设置CAS授权过滤器
            .addFilterBefore(casLogoutFilter(),LogoutFilter.class)      //登出配置
            .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class);//登出配置
}

过滤器以及授权认证类的实现

/***
 * UserDetailsServiceImpl在SpringIOC容器中
 */
@Autowired
private UserDetailsService userDetailsService;

//Cas认证入口
@Bean
public CasAuthenticationEntryPoint casAuthenticationEntryPoint(){
    //用于配置Cas认证入口信息
    CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
    //设置登录地址
    casAuthenticationEntryPoint.setLoginUrl(casProperties.getCasServerLoginUrl());
    //返回的服务信息
    casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
    return  casAuthenticationEntryPoint;
}

/****
 * 服务配置信息
 * @return
 */
@Bean
public ServiceProperties serviceProperties(){
    //服务信息配置
    ServiceProperties serviceProperties = new ServiceProperties();
    //设置应用访问信息
    serviceProperties.setService(casProperties.getAppServerUrl()+casProperties.getAppLoginUrl());
    //针对非空登录用户进行身份校验
    serviceProperties.setAuthenticateAllArtifacts(true);
    return  serviceProperties;
}


/**CAS认证过滤器*/
@Bean
public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
    //设置CAS授权过滤器
    CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
    //集成SpringSecurity授权认证器
    casAuthenticationFilter.setAuthenticationManager(authenticationManager());
    casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLoginUrl());
    return casAuthenticationFilter;
}

/**
 * cas 认证 Provider
 * */
@Bean
public CasAuthenticationProvider casAuthenticationProvider() {
    //创建CAS授权认证器
    CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
    //集成自定义授权认证器
    casAuthenticationProvider.setUserDetailsService(userDetailsService);
    //设置Cas授权认证器相关配置
    casAuthenticationProvider.setServiceProperties(serviceProperties());
    //设置票据校验器
    casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
    casAuthenticationProvider.setKey("casAuthenticationProviderKey");
    return casAuthenticationProvider;
}

/**
 * 设置票据校验地址-CAS地址
 * @return
 */
@Bean
public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
    return new Cas20ServiceTicketValidator(casProperties.getCasServerUrl());
}

/**单点登出过滤器*/
@Bean
public SingleSignOutFilter singleSignOutFilter() {
    SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
    singleSignOutFilter.setCasServerUrlPrefix(casProperties.getCasServerUrl());
    singleSignOutFilter.setIgnoreInitConfiguration(true);
    return singleSignOutFilter;
}

/**请求单点退出过滤器*/
@Bean
public LogoutFilter casLogoutFilter() {
    LogoutFilter logoutFilter = new LogoutFilter(casProperties.getCasServerLogoutUrl(), new SecurityContextLogoutHandler());
    logoutFilter.setFilterProcessesUrl(casProperties.getAppLogoutUrl());
    return logoutFilter;
}

5.2.4 完整代码

@Component
@EnableWebSecurity      //开启SpringSecurity注解配置
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CasProperties casProperties;

    //三个方法的方法名都是:configure

    /***
     * 1)忽略某些地址的安全校验
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/image/**");
        web.ignoring().antMatchers("/403.html");
    }

    /***
     * 2)设置需要拦截过滤的地址的安全校验规则
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //除了上面忽略安全校验的地址,其他的一律需要ROLE_ADMIN角色权限访问
        http.authorizeRequests().anyRequest().access("hasAnyRole('ADMIN')");

        //允许iframe的使用
        http.headers().frameOptions().disable();

        //禁止csrf
        http.csrf().disable();

        //开启登录功能
        http.formLogin();

        //开启登出功能
        http.logout();

        //异常处理
        http.exceptionHandling().accessDeniedPage("/403.html")
                .authenticationEntryPoint(casAuthenticationEntryPoint())    //设置自定义授权认证类
                .and()
                .addFilter(casAuthenticationFilter())                       //设置CAS授权过滤器
                .addFilterBefore(casLogoutFilter(),LogoutFilter.class)      //登出配置
                .addFilterBefore(singleSignOutFilter(), CasAuthenticationFilter.class);//登出配置
    }


    /***
     * UserDetailsServiceImpl在SpringIOC容器中
     */
    @Autowired
    private UserDetailsService userDetailsService;

    //Cas认证入口
    @Bean
    public CasAuthenticationEntryPoint casAuthenticationEntryPoint(){
        //用于配置Cas认证入口信息
        CasAuthenticationEntryPoint casAuthenticationEntryPoint = new CasAuthenticationEntryPoint();
        //设置登录地址
        casAuthenticationEntryPoint.setLoginUrl(casProperties.getCasServerLoginUrl());
        //返回的服务信息
        casAuthenticationEntryPoint.setServiceProperties(serviceProperties());
        return  casAuthenticationEntryPoint;
    }

    /****
     * 服务配置信息
     * @return
     */
    @Bean
    public ServiceProperties serviceProperties(){
        //服务信息配置
        ServiceProperties serviceProperties = new ServiceProperties();
        //设置应用访问信息
        serviceProperties.setService(casProperties.getAppServerUrl()+casProperties.getAppLoginUrl());
        //针对非空登录用户进行身份校验
        serviceProperties.setAuthenticateAllArtifacts(true);
        return  serviceProperties;
    }


    /**CAS认证过滤器*/
    @Bean
    public CasAuthenticationFilter casAuthenticationFilter() throws Exception {
        //设置CAS授权过滤器
        CasAuthenticationFilter casAuthenticationFilter = new CasAuthenticationFilter();
        //集成SpringSecurity授权认证器
        casAuthenticationFilter.setAuthenticationManager(authenticationManager());
        casAuthenticationFilter.setFilterProcessesUrl(casProperties.getAppLoginUrl());
        return casAuthenticationFilter;
    }

    /**
     * cas 认证 Provider
     * */
    @Bean
    public CasAuthenticationProvider casAuthenticationProvider() {
        //创建CAS授权认证器
        CasAuthenticationProvider casAuthenticationProvider = new CasAuthenticationProvider();
        //集成自定义授权认证器
        casAuthenticationProvider.setUserDetailsService(userDetailsService);
        //设置Cas授权认证器相关配置
        casAuthenticationProvider.setServiceProperties(serviceProperties());
        //设置票据校验器
        casAuthenticationProvider.setTicketValidator(cas20ServiceTicketValidator());
        casAuthenticationProvider.setKey("casAuthenticationProviderKey");
        return casAuthenticationProvider;
    }

    /**
     * 设置票据校验地址-CAS地址
     * @return
     */
    @Bean
    public Cas20ServiceTicketValidator cas20ServiceTicketValidator() {
        return new Cas20ServiceTicketValidator(casProperties.getCasServerUrl());
    }

    /**单点登出过滤器*/
    @Bean
    public SingleSignOutFilter singleSignOutFilter() {
        SingleSignOutFilter singleSignOutFilter = new SingleSignOutFilter();
        singleSignOutFilter.setCasServerUrlPrefix(casProperties.getCasServerUrl());
        singleSignOutFilter.setIgnoreInitConfiguration(true);
        return singleSignOutFilter;
    }

    /**请求单点退出过滤器*/
    @Bean
    public LogoutFilter casLogoutFilter() {
        LogoutFilter logoutFilter = new LogoutFilter(casProperties.getCasServerLogoutUrl(), new SecurityContextLogoutHandler());
        logoutFilter.setFilterProcessesUrl(casProperties.getAppLogoutUrl());
        return logoutFilter;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352