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; } }
调用自定义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访问