Spring Security OAuth2 JWT实现SSO

 转载务必说明出处:https://blog.csdn.net/LiaoHongHB/article/details/84032850

     在这里我们以一台服务器和2台客户端做测试,在客户端1进行登陆之后,访问客服端2的时候不需要进行登陆就可访问(类似于淘宝登陆之后,在淘宝网点击天猫链接会发现天猫网已经是登陆状态)

       jwt-server代码:

          资源服务器:

@Configuration
@EnableWebSecurity
public class SsoSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .csrf().disable();
    }
}

          认证服务器:

@Configuration
@EnableAuthorizationServer
public class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("client1")
                .secret("clientsecret1")
                //支持的授权模式(数组类型)
                .authorizedGrantTypes("authorization_code", "refresh_token")
                .scopes("all")
                .and()
                .withClient("client2")
                .secret("clientsecret2")
                .authorizedGrantTypes("authorization_code", "refresh_token")
                .scopes("all");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(jwtTokenStore()).accessTokenConverter(jwtAccessTokenConverter());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("isAuthenticated()");
    }

    @Bean
    public TokenStore jwtTokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        //JWT签名
        converter.setSigningKey("jwt");
        return converter;
    }
}

UserDetailService:

@Component
public class SsoUserDetailService implements UserDetailsService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return new User(username,passwordEncoder.encode("123456"),
                AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN"));
    }
}

Controller:

@RestController
@SessionAttributes("authorizationRequest")
public class SsoApprovalEndpointController {

    @RequestMapping({"/oauth/confirm_access"})
    public ModelAndView getAccessConfirmation(Map model, HttpServletRequest request) throws Exception {
        String template = this.createTemplate(model, request);
        if (request.getAttribute("_csrf") != null) {
            model.put("_csrf", request.getAttribute("_csrf"));
        }

        return new ModelAndView(new SsoSpelView(template), model);
    }

    protected String createTemplate(Map model, HttpServletRequest request) {
        String template = TEMPLATE;
        if (!model.containsKey("scopes") && request.getAttribute("scopes") == null) {
            template = template.replace("%scopes%", "").replace("%denial%", DENIAL);
        } else {
            template = template.replace("%scopes%", this.createScopes(model, request)).replace("%denial%", "");
        }

        if (!model.containsKey("_csrf") && request.getAttribute("_csrf") == null) {
            template = template.replace("%csrf%", "");
        } else {
            template = template.replace("%csrf%", CSRF);
        }

        return template;
    }

    private CharSequence createScopes(Map model, HttpServletRequest request) {
        StringBuilder builder = new StringBuilder("
    "); Map scopes = (Map)((Map)(model.containsKey("scopes") ? model.get("scopes") : request.getAttribute("scopes"))); Iterator var5 = scopes.keySet().iterator(); while(var5.hasNext()) { String scope = (String)var5.next(); String approved = "true".equals(scopes.get(scope)) ? " checked" : ""; String denied = !"true".equals(scopes.get(scope)) ? " checked" : ""; String value = SCOPE.replace("%scope%", scope).replace("%key%", scope).replace("%approved%", approved).replace("%denied%", denied); builder.append(value); } builder.append("
"); return builder.toString(); } private static String CSRF = ""; private static String DENIAL = "
%csrf%
"; private static String TEMPLATE = "" + "" + "
"+ "

OAuth Approval

" + "

Do you authorize '${authorizationRequest.clientId}' to access your protected resources?

" + "
" + "%csrf%%scopes%" + "" + "
" + "%denial%" + "
"+ ""+ "" + ""; private static String SCOPE = "
  • %scope%: Approve Deny
  • "; }

    View.class:

    public class SsoSpelView implements View {
    
        private final String template;
    
        private final String prefix;
    
        private final SpelExpressionParser parser = new SpelExpressionParser();
    
        private final StandardEvaluationContext context = new StandardEvaluationContext();
    
        private PropertyPlaceholderHelper.PlaceholderResolver resolver;
    
        public SsoSpelView(String template) {
            this.template = template;
            this.prefix = new RandomValueStringGenerator().generate() + "{";
            this.context.addPropertyAccessor(new MapAccessor());
            this.resolver = new PropertyPlaceholderHelper.PlaceholderResolver() {
                public String resolvePlaceholder(String name) {
                    Expression expression = parser.parseExpression(name);
                    Object value = expression.getValue(context);
                    return value == null ? null : value.toString();
                }
            };
        }
    
        public String getContentType() {
            return "text/html";
        }
    
        public void render(Map model, HttpServletRequest request, HttpServletResponse response)
                throws Exception {
            Map map = new HashMap(model);
            String path = ServletUriComponentsBuilder.fromContextPath(request).build()
                    .getPath();
            map.put("path", (Object) path==null ? "" : path);
            context.setRootObject(map);
            String maskedTemplate = template.replace("${", prefix);
            PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper(prefix, "}");
            String result = helper.replacePlaceholders(maskedTemplate, resolver);
            result = result.replace(prefix, "${");
            response.setContentType(getContentType());
            response.getWriter().append(result);
        }
    }
    

    client1代码:

    application.yml:

    server:
      port: 5001
      servlet:
        context-path: /client1
    
    security:
      oauth2:
        client:
          client-id: client1
          client-secret: clientsecret1
          user-authorization-uri:  http://127.0.0.1:5000/server/oauth/authorize
          access-token-uri:  http://127.0.0.1:5000/server/oauth/token
        resource:
          jwt:
            key-uri:  http://127.0.0.1:5000/server/oauth/token_key

    index.jsp:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        sso client2
    
    
          

    SSO CLIENT2 DEMO


    访问client1

    client2代码:

    application.yml:

    server:
      port: 5002
      servlet:
        context-path: /client2
    
    security:
      oauth2:
        client:
          client-id: client2
          client-secret: clientsecret2
          user-authorization-uri:  http://127.0.0.1:5000/server/oauth/authorize
          access-token-uri:  http://127.0.0.1:5000/server/oauth/token
        resource:
          jwt:
            key-uri:  http://127.0.0.1:5000/server/oauth/token_key

    index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    
        sso client2
    
    
          

    SSO CLIENT2 DEMO


    访问client1

    测试:先运行server,然后客户端。

    地址栏输入:localhost:5001/client1/index.jsp  --->回车键

    然后会跳转到:localhost:5000/sever/login

    输入用户名和密码:这里为了方便测试,用户名可以随便输,密码必须为123456

    Spring Security OAuth2 JWT实现SSO_第1张图片

    点击Login按钮即返回到client1/index.jsp页面

    Spring Security OAuth2 JWT实现SSO_第2张图片

    这个时候点击“访问client2”,在不需要登陆的情况下就可以访问到client2/index.jsp页面(即完成单点登陆类似于淘宝登陆天猫)

    Spring Security OAuth2 JWT实现SSO_第3张图片

     在client2/index.jsp中访问client1也是不需要登陆就可访问了。

    你可能感兴趣的:(JWT,springsecurity,springboot,oauth2,sso)