springsecurity 授权

springsecurity 授权就是控制访问请求,通俗说就是控制url

具体做了些什么?

1、认证失败会跳转到登录页面

2、根据权限访问

3、根据角色访问

4、没有权限的页面展示

授权

    //授权:针对url的设置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/test/**").hasAuthority("part")
                .antMatchers("/admin/**").hasAuthority("admin")
                .anyRequest().authenticated()
        .and().formLogin();
    }

HttpSecurity对象的方法

http.formLogin()//操作登录相关
http.authorizeRequests()//操作请求相关
http.exceptionHandling()//异常相关
http.logout()//注销相关
http.rememberMe()//记住我

HttpSesurity对象方法之间可以使用.and()衔接

http.formLogin().and().logout().and().authorizeRequests()........

formLogin  

.loginPage("")  //登录页面
.failureForwardUrl("") //登录提交失败后,转发地址
.successForwardUrl("") //登录提交成功后,转发地址
.loginProcessingUrl("")//登录提交处理地址
.defaultSuccessUrl("")//登录提交成功后,跳转地址
.passwordParameter("pwd") //密码对应key
.usernameParameter("uname") //用户名对应key
http.formLogin()
                        //自定义登录页面
                        .loginPage("/login.html")
                        //必须和表单提交的接口一样,会去执行自定义登录逻辑
                        .loginProcessingUrl("/login")

                        //访问不存在的请求
                        //1、会跳转到登录页面
                        //2、登录成功,正常会跳转到提示请求不存在页面
                        // alwaysUse:true,会跳转到main.html
                        .defaultSuccessUrl("/main.html",true)
                        .defaultSuccessUrl("/toMain",true)
                        //不限制请求方式GET、POST都可以访问
                        //.defaultSuccessUrl("/main.html")

                        // 会报There was an unexpected error (type=Method Not Allowed, status=405).
                        //.successForwardUrl("/main.html")
                        //登录成功或转发的页面,只允许POST请求
                        .successForwardUrl("/toMain")
                        .failureForwardUrl("/toError");
                        //调用自定义Handler
//                      .successHandler(new MyAuthenticationSuccessHandler())
//                      .failureHandler(new MyAuthenticationFailureHandler())

.loginProcessingUrl("/login")与form标签的action属性值一致

<form action="/login" method="post">
    用户名:<input type="text" name="username"/> //默认登录key:username  通过usernameParameter方法修改默认值
    密 码:<input type="password" name="password"/> //默认密码key:password  通过passwordParameter方法修改默认值
    <button type="submit" >submit</button>
</form>

.defaultSuccessUrl("/main.html",true)、.defaultSuccessUrl("/tomain",true):不限制请求方式

    public final T defaultSuccessUrl(String defaultSuccessUrl, boolean alwaysUse) {
        SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler();
        handler.setDefaultTargetUrl(defaultSuccessUrl);
        handler.setAlwaysUseDefaultTargetUrl(alwaysUse);
        this.defaultSuccessHandler = handler;
        return successHandler(handler);
    }

.successForwardUrl("/toMain")、.failureForwardUrl("/toError"):只允许POST请求

    public FormLoginConfigurer<H> failureForwardUrl(String forwardUrl) {
        failureHandler(new ForwardAuthenticationFailureHandler(forwardUrl));
        return this;
    }

.successHandler(new MyAuthenticationSuccessHandler("Url"))、.failureHandler(new MyAuthenticationFailureHandler("Url")):调用自定义Handler

public class xxxxHandler implements AuthenticationFailureHandler {

    private final String forwardUrl;

    /**
     * @param forwardUrl
     */
    public ForwardAuthenticationFailureHandler(String forwardUrl) {
        Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl), () -> "'" + forwardUrl + "' is not a valid forward URL");
        this.forwardUrl = forwardUrl;
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException exception) throws IOException, ServletException {
        request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
        request.getRequestDispatcher(this.forwardUrl).forward(request, response);
    }

}

authorizeRequests 

.anyRequest()//任何请求
.antMatchers("")//指定请求  
对请求指定访问范围
  .permitAll() // 不做任何限制连登录校验都不做
.hasIpAddress()//指定ip访问
.fullyAuthenticated()
.denyAll()//拒绝所有权限/角色的访问
.access("") //所有的访问控制方法都是基于access,permitAll()等价于access("permitAll"),hasRole("abc") 等价于 access("hasRole('abc')")
.authenticated()//需要登录
.hasAuthority(String)//指定权限允许访问
.hasAnyAuthority(String ...)//包含指定权限允许访问
.hasAnyRole(String ...)//包含指定角色允许访问
.hasRole(String)//指定角色允许访问

注意:hasRole、hasAnyRole方法

    private static String hasRole(String role) {
        Assert.notNull(role, "role cannot be null");
        Assert.isTrue(!role.startsWith("ROLE_"),
                () -> "role should not start with 'ROLE_' since it is automatically inserted. Got '" + role + "'");
        return "hasRole('ROLE_" + role + "')";
    }

角色前添加前缀,所以我们在认证设置角色时也必须添加ROLE前缀

 

    //授权:针对url的设置
    @Override
    protected void configure(HttpSecurity http) throws Exception {

                http.authorizeRequests()
                .antMatchers("/test/**").hasRole("guest")
                .antMatchers("/admin/**").hasRole("admin")
                .anyRequest().authenticated()
                .and().formLogin();
    }

自定义access

@Component
public class MyAccessImpl implements MyAccess {
    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        //获取用户
        Object principal =  authentication.getPrincipal();

        if(principal instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) principal;
            Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
            //request.getRequestURI() => /xxx.html
            //权限是否包含/xxx.html
            //查看认证时有没有设置对应权限.authorities(AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));
            return authorities.contains(new SimpleGrantedAuthority(request.getRequestURI()));
        }
        return false;
    }
}
View Code

调用自定义access方法

.anyRequest().access("@myAccessImpl.hasPermission(request,authentication)");//.authenticated();

 

exceptionHandling 

.accessDeniedPage("")//指定没有权限访问页面 
    public ExceptionHandlingConfigurer<H> accessDeniedPage(String accessDeniedUrl) {
        AccessDeniedHandlerImpl accessDeniedHandler = new AccessDeniedHandlerImpl();
        accessDeniedHandler.setErrorPage(accessDeniedUrl);
        return accessDeniedHandler(accessDeniedHandler);
    }

自定义403处理

public class myAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setStatus(HttpServletResponse.SC_ACCEPTED);

        response.setHeader("Content-Type","application/json;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.write("{\"status\":\"error\"}");
        writer.flush();
        writer.close();
    }
}

使用自定义

http.exceptionHandling().accessDeniedHandler(new myAccessDeniedHandler());

编辑授权(基于IP   request.getRemoteAddr())

http.authorizeRequests()
                .antMatchers("/login.html").permitAll()
                .antMatchers("/add.html").hasIpAddress("127.0.0.1")
                .anyRequest().authenticated();

效果:localhost访问

127.0.0.1访问

 

 

posted @ 2021-08-12 16:36  一杯水M  阅读(197)  评论(0编辑  收藏  举报