重定向到登录页面或根据请求的URL给出403错误

时间:2019-06-04 21:27:47

标签: java spring-boot spring-mvc spring-security

我有一个使用Spring Boot使用安全性制作的应用程序。此应用程序使用MVC来显示一些页面,还使用一些其他界面来更新/获取对象。

现在,我在未登录的情况下提出的每个请求都会重定向到 / login 页面。

当我尝试从Web浏览器访问时,此操作按预期进行。但是,当我尝试从页面访问某些特定路径(例如“ / api / customers”)时,我希望应用做出不同的反应。

如果我尝试访问该路径,我想丢弃HTTP 403错误,而不是重定向到登录页面。

这是我的安全配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.headers()
            .referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN);

    http.authorizeRequests()
            .antMatchers("/js/**", "/img/**")
            .permitAll()
            .antMatchers("/**").authenticated()
            .and()
            .csrf().disable()
            .formLogin()
            .loginPage("/login")
            .usernameParameter("email")
            .passwordParameter("password")
            .and()
            .logout()
            .logoutUrl("/logout")
            .logoutSuccessUrl("/login?logged-out")
            .and()
            .exceptionHandling()
            .accessDeniedPage("/access-denied")

    ;
}

这可能吗?

1 个答案:

答案 0 :(得分:0)

您可以创建自定义AuthenticationEntryPoint:

https://docs.spring.io/spring-security/site/docs/4.0.4.RELEASE/reference/htmlsingle/#auth-entry-point

  

如果用户请求一个AuthenticationEntryPoint,则将调用   安全的HTTP资源,但未通过身份验证。一个合适的   AuthenticationException或AccessDeniedException将由   安全拦截器进一步向下调用堆栈,触发   在入口点开始方法。这是呈现的工作   对用户的适当响应,以便身份验证可以开始。

const fs = require('fs');

// Don't do if dist not existing
if (!fs.existsSync('./dist')) return;
if (!fs.existsSync('./dist/myProject/stats.json')) return;

// Remove previous file
if (fs.existsSync('./dist/myProject/bundle-chunks.json')) fs.unlinkSync('./dist/myProject/bundle-chunks.json');

// Read file, parse to JSON
const statsStr = fs.readFileSync('./dist/myProject/stats.json').toString();
const statsJson = JSON.parse(statsStr);

// Get corresponding property
const assets = statsJson.assetsByChunkName;

// Transform the object into an array with more information
const payload = Object.keys(assets).reduce((pk, nk) => {
  const key = nk;
  const ext = assets[nk].split('.').pop();
  const path = assets[nk];
  pk.push({ key, ext, path });
  return pk;
}, []);

// Reduce the array to build a JSON object of typ { scripts: [], styles: [] }
const metas = payload.reduce((p, n) => {
  if (n.ext === 'js')
    p.scripts.push(`<script type="text/javascript" src="./${n.path}" ${n.path.includes('polyfill') ? 'nomodule' : ''}></script>`);
  if (n.ext === 'css')
    p.styles.push(`<link rel="stylesheet" href="./${n.path}">`);
  return p;
}, { styles: [], scripts: [] });

// Save in file
fs.writeFileSync('./dist/myProject/bundle-chunks.json', JSON.stringify(metas, null, 2));

// Notify
console.log('Bundle chunks written to bundle-chunks.json file');

// Scripts files are to be added to the end of the body (to incread load time and let the page display itself while loading)
// Style files are to be added to the head of the application.

并在框架中注册:

@Component
public class Http401UnauthorizedEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, 
                               AuthenticationException ex)
            throws IOException, ServletException {

        boolean somePath = request.getServletPath().equals("/somePath");

        if(somePath){
            response.sendError(SC_FORBIDDEN, "Access Denied");
        }
        else{
            response.sendRedirect("/login");
        }
    }
}